Strange behavior of int()

Hi,

In my code, I have a section that transforms a numpy float64 to an int. I am getting 52, while all my other coworkers are getting 53. The code is:

import numpy as np 

tmp_size = 23426
all_roots = np.roots([1, -3, 2, -6*tmp_size]) 
flag1 = all_roots>0
flag2 = np.isreal(all_roots)
print(all_roots)
mat_col_num = all_roots[flag1 & flag2]
print(mat_col_num)
mat_col_num = np.real(mat_col_num)
print(mat_col_num.dtype)
mat_col_num = int(mat_col_num)
# mat_col_num = np.int64(mat_col_num)
# mat_col_num = mat_col_num.astype(int)
print(mat_col_num)

For now, I have found out that if I use np.round() before int() I also get 53 like others. I have also used np.int64() and .astype(int) but still get 52. to make sure the issue is not my Python and NumPy version, I also created a new conda environment with the exact Python (3.9.15) and NumPy (1.24.3) version as my friend who is getting 53. still getting 52.

I simply do not understand what is happening. So any help would be appreciated.

What does all_roots[0] give you? I get this:

>>> all_roots[0]
(53.00000000000001+0j)
>>> all_roots[0]-53
(7.105427357601002e-15+0j)

(Python 3.11.1 and numpy 1.25.2)

I get -7.815970093361102e-14+0j

So, the difference is due to rounding error, and a small one at that.

I got the same answer with both numpy 1.23.x and 1.25.2, but using Python 3.11.1 for both. Oh, and on Windows 10.

Are the coworkers also using conda, on the same OS?
Maybe the BLAS / LAPACK / MKL backend is different?

print(np.show_config())

I get this when I run np.show_config()

blas_armpl_info:
  NOT AVAILABLE
blas_mkl_info:
    libraries = ['mkl_rt', 'pthread']
    library_dirs = ['/home/users/afaghiri/miniconda3/envs/test/lib']
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['/home/users/afaghiri/miniconda3/envs/test/include']
blas_opt_info:
    libraries = ['mkl_rt', 'pthread']
    library_dirs = ['/home/users/afaghiri/miniconda3/envs/test/lib']
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['/home/users/afaghiri/miniconda3/envs/test/include']
lapack_armpl_info:
  NOT AVAILABLE
lapack_mkl_info:
    libraries = ['mkl_rt', 'pthread']
    library_dirs = ['/home/users/afaghiri/miniconda3/envs/test/lib']
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['/home/users/afaghiri/miniconda3/envs/test/include']
lapack_opt_info:
    libraries = ['mkl_rt', 'pthread']
    library_dirs = ['/home/users/afaghiri/miniconda3/envs/test/lib']
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['/home/users/afaghiri/miniconda3/envs/test/include']
Supported SIMD extensions in this NumPy install:
    baseline = SSE,SSE2,SSE3
    found = SSSE3,SSE41,POPCNT,SSE42,AVX,F16C,FMA3,AVX2
    not found = AVX512F,AVX512CD,AVX512_KNL,AVX512_KNM,AVX512_SKX,AVX512_CLX,AVX512_CNL,AVX512_ICL
None

While my coworkers get this

openblas64__info:
    libraries = ['openblas64_', 'openblas64_']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None), ('BLAS_SYMBOL_SUFFIX', '64_'), ('HAVE_BLAS_ILP64', None)]
    runtime_library_dirs = ['/usr/local/lib']
blas_ilp64_opt_info:
    libraries = ['openblas64_', 'openblas64_']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None), ('BLAS_SYMBOL_SUFFIX', '64_'), ('HAVE_BLAS_ILP64', None)]
    runtime_library_dirs = ['/usr/local/lib']
openblas64__lapack_info:
    libraries = ['openblas64_', 'openblas64_']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None), ('BLAS_SYMBOL_SUFFIX', '64_'), ('HAVE_BLAS_ILP64', None), ('HAVE_LAPACKE', None)]
    runtime_library_dirs = ['/usr/local/lib']
lapack_ilp64_opt_info:
    libraries = ['openblas64_', 'openblas64_']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None), ('BLAS_SYMBOL_SUFFIX', '64_'), ('HAVE_BLAS_ILP64', None), ('HAVE_LAPACKE', None)]
    runtime_library_dirs = ['/usr/local/lib']
Supported SIMD extensions in this NumPy install:
    baseline = SSE,SSE2,SSE3
    found = SSSE3,SSE41,POPCNT,SSE42,AVX,F16C,FMA3,AVX2
    not found = AVX512F,AVX512CD,AVX512_KNL,AVX512_KNM,AVX512_SKX,AVX512_CLX,AVX512_CNL,AVX512_ICL
None

And one of my coworkers use conda. And we are on the same cluster. so the same machine.

1 Like

OK, so the difference is presumably the numpy backend, one is using openblas and the other is using mkl. These probably implement the root finding slightly differently. This has nothing to do with int().

Yeah. it seems the difference is between BLAS vs MKL libraries. based on https://numpy.org/install/ the library Numpy uses depends on the installation command. if pip is used or conda with conda-forge channel, OpenBLAS or BLAS is used. but conda itself install Numpy with MKL. I guess I found a corner case. I guess the best thing to do is just round the number before making it int.

1 Like

If you really need exact results and cannot afford any kind of floating-point imprecision, and both convenience and correctness are more important than speed (this is dozens of times slower), symbolic computation is a better tool for the job.

>>> import sympy
>>> tmp_size = 23426
>>> x = sympy.symbols('x')
>>> sympy.solve(1*x**3 + -3*x**2 + 2*x + -6*tmp_size)
[53, -25 - sqrt(2027)*I, -25 + sqrt(2027)*I]