I encountered an odd situation in Python (version 3.9.8) and numpy (version 1.20.0)trying to convert float64 numbers to int. It started with calculating the fft coefficients with numpy and then using inverse DFT with
x = np.array([1, -4, 2, 2, 1, -4, 6, 2]) # test vector
X = np.fft.fft(x) # calc fft coefficients
The result is fine so far:
print(X)
[ 6. 0.j 0. 4.j -6. 12.j 0. -4.j 14. 0.j 0. 4.j -6.-12.j 0. -4.j]
Now I've written my own inverse DFT and get correct results:
N = len(X) # number of samples N
y = np.zeros(N) # create empty result vector with N elements
# calc inverse DFT
for n in np.arange(N):
sum = 0
for k in np.arange(N):
sum = sum X[k] * np.exp(1j * 2* np.pi * k * n/N)
y[n] = sum.real/N
# print results
print(y)
[ 1. -4. 2. 2. 1. -4. 6. 2.]
The resulting vector is also fine.
But when I convert this vector to int
strange things happen. IIn the second half of the vector, values change in ways that are inexplicable to me.
print(y.astype('int'))
[ 1 -4 2 2 0 -3 6 1]
Any idea?
CodePudding user response:
astype(int)
will truncate values to integers: it just ditches the part after the decimal period. And the floating point values you see on your screen, are rounded representations: 2.
is probably something like 1.99999999
because of floating point imprecisions.
First, round the values, then convert them to integer:
np.round(y)
produces
array([ 1., -4., 2., 2., 1., -4., 6., 2.])
which are still floating point values, but now rounded to integer values (note that all (machine-range) integers can be represented exactly by floating point numbers).
Thus do the following:
np.round(y).astype(int)
to get
array([ 1, -4, 2, 2, 1, -4, 6, 2])
CodePudding user response:
Here is a quick explaination of the issue with the solution:
import numpy
lst = numpy.array([-3.99999999999])
print(f"{lst = }") # array([-4.])
print(f"{lst.astype('int')}") # array([-3])
print(f"{numpy.round(lst).astype('int')}") # array([-4])
It is just a display error here. the print of the numpy array don t show you all digits.
Tranform in an integer will remove all digits of float. Then if you are under 4 (even at e-10) you will be int at 3. You have to round your result before change to int type.
print(int(3.99999999)) # 3
print(round(3.99999999)) # 4
CodePudding user response:
Use numpy.ndarray.astype(dtype)
with dtype as int to convert the float array numpy.ndarray into an array of integers.
Eg:
print(float_array)
[[3. 2.3]
[3.5 4.7]]
int_array = float_array.astype(int)
print(int_array)
[[3 2] [3 4]]
Also note that astype will always round each number down. To round up or to the nearest integer, use numpy.ceil()
or numpy.rint()
.