With your setup - I like to see some values, not just a vague "not the same" claim.
In [70]: Y
Out[70]:
array([3.20000000e+01, 5.12000000e+02, 4.09600000e+03, 8.19200000e+03,
1.63840000e+04, 5.24288000e+05, 8.38860800e+06, 6.71088640e+07,
1.34217728e+08, 4.29496730e+09, 6.87194767e+10, 5.49755814e+11,
1.09951163e+12, 3.51843721e+13, 5.62949953e+14, 4.50359963e+15,
9.00719925e+15, 2.88230376e+17, 4.61168602e+18, 1.84467441e+19,
3.68934881e+19, 7.37869763e+19, 2.36118324e+21])
In [72]: X
Out[72]: bytearray(b'\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x01\x01\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x01\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x01\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x01\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x01\x01\x01\x00\x00\x00\x00\x01')
In [73]: for i in range(len(sb)):
...: vl_1 = vl_1+X[i]*2**(i+1)
...:
In [74]: vl_1
Out[74]: 2495224477001068343840
In [76]: for y in np.nditer(Y) :
...: vl_2=vl_2+y
...:
In [77]: vl_2
Out[77]: 2.4952244770010683e+21
One is float (after all Y
is float), but otherwise the values are the same (within float precision)
In [78]: vl_1-vl_2
Out[78]: 0.0
nditer
does nothing for you:
In [79]: vl_2=0
...: for y in Y : vl_2=vl_2+y
In [80]: vl_2
Out[80]: 2.4952244770010683e+21
but iterating on arrays is slower. You don't need it
In [81]: np.sum(Y)
Out[81]: 2.4952244770010683e+21
edit
If you replace 2.
with 2
when constructing Y
:
In [95]: 2.**(np.nonzero(X)[0]+1)
Out[95]:
array([3.20000000e+01, 5.12000000e+02, 4.09600000e+03, 8.19200000e+03,
1.63840000e+04, 5.24288000e+05, 8.38860800e+06, 6.71088640e+07,
1.34217728e+08, 4.29496730e+09, 6.87194767e+10, 5.49755814e+11,
1.09951163e+12, 3.51843721e+13, 5.62949953e+14, 4.50359963e+15,
9.00719925e+15, 2.88230376e+17, 4.61168602e+18, 1.84467441e+19,
3.68934881e+19, 7.37869763e+19, 2.36118324e+21])
In [96]: 2**(np.nonzero(X)[0]+1)
Out[96]:
array([ 32, 512, 4096,
8192, 16384, 524288,
8388608, 67108864, 134217728,
4294967296, 68719476736, 549755813888,
1099511627776, 35184372088832, 562949953421312,
4503599627370496, 9007199254740992, 288230376151711744,
4611686018427387904, 0, 0,
0, 0], dtype=int64)
The second is integer values, but the last 4 are too large for int64
.
Skipping the last part of X
I get the same integer result:
In [100]: sum(2**(np.nonzero(X[:-8])[0]+1))
Out[100]: 4914027050278875680
In [101]: sum([x*2**(i+1) for i,x in enumerate(X[:-8])])
Out[101]: 4914027050278875680
The other answer suggested going with object
dtype. While it may work, it looses most of the speed advantages of working with numeric dtype arrays.
object speed
As proposed in the other answer, converting the nonzero
results to object
, produces the large enough Python ints:
In [166]: 2**(np.nonzero(X)[0]+1).astype(object)
Out[166]:
array([32, 512, 4096, 8192, 16384, 524288, 8388608, 67108864, 134217728,
4294967296, 68719476736, 549755813888, 1099511627776,
35184372088832, 562949953421312, 4503599627370496,
9007199254740992, 288230376151711744, 4611686018427387904,
18446744073709551616, 36893488147419103232, 73786976294838206464,
2361183241434822606848], dtype=object)
Some comparative times
In [167]: timeit np.sum(2**(np.nonzero(X)[0]+1).astype(object))
46.5 µs ± 1.64 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
The approximate float approach:
In [168]: timeit np.sum(2.**(np.nonzero(X)[0]+1))
32.3 µs ± 1.12 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
The enumerated list:
In [169]: timeit sum([x*2**(i+1) for i,x in enumerate(X)])
43.1 µs ± 1.14 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
Working with an object dtype array doesn't help, speedwise.
The list version of nonzero_bits is even faster
In [173]: %%timeit
...: nonzero_bits = [i for i, x in enumerate(X) if x != 0]
...: vl = sum(2 ** (i + 1) for i in nonzero_bits)
18.9 µs ± 221 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)