Conner M.
Conner M.

Reputation: 2074

numpy.prod returns negative value for list of all positive integers

I've completed Euler Project problem #8 (the answer is not included in this question), but ran into some unexpected behavior with numpy.prod. The function returned negative numbers for some list of all positive, single-digit integers. This looks related to this question.

import numpy as np

# this implementation doesn't work
np.prod(list(map(int, '9478851843858'))) 
Out[139]: -1817706496

# but these do
np.prod(np.array(list(map(int, '9478851843858'  )), dtype='int64'))
Out[141]: 2477260800

reduce((lambda x, y: x*y),list(map(int,list('9478851843858'))))
Out[144]: 2477260800

These are other examples:

 ('3975369781797', -514256656),
 ('9476545682848', -579076096),
 ('4765456828489', -579076096),
 ('7536978179778', -748460672),
 ('8694788518438', -1322254336),
 ('5397536978179', -1594459696),
 ('6652947654568', -1682231296),
 ('9478851843858', -1817706496)]

But not these:

 ('4788518438586', 1651507200),
 ('6978179778461', 1792336896),
 ('8787992724428', 1820786688),
 ('6947885184385', 1857945600),
 ('4355766896648', 1975599104),
 ('5576689664895', 2039787520),
 ('9194934969835', 2040733440),
 ('9878799272442', 2048385024),
 ('8617866458359', 2090188800),
 ('9781797784617', 2091059712)]

What about passing the python list to np.prod causes it to return a negative integer?

Upvotes: 0

Views: 437

Answers (1)

ForceBru
ForceBru

Reputation: 44838

NumPy is written in C and C++, and it doesn't have the "unbounded" integer type that Python has. So all integers are of widths your CPU supports. This means that overflows and underflows can occur.

Take a look at this C code:

#include <stdio.h>
#include <stdint.h>

int main(void) {
    int64_t data = 2477260800ULL;
    printf("i64: %lld, i32: %d\n", data, (int32_t)data);
}

And here's the output:

~> clang test.c
~> ./a.out
i64: 2477260800, i32: -1817706496

So it looks like your NumPy is using 32-bit signed integers that can't contain the unsigned number 2477260800 because bin(2477260800) == '0b10010011101010000000000000000000', and that's a negative int32_t.

Upvotes: 3

Related Questions