What precision does numpy.float128
map to internally? Is it __float128
or long double? Or something else entirely?
A potential follow on question if anybody knows: is it safe in C to cast a __float128
to a (16 byte) long double, with just a loss in precision? (this is for interfacing with a C lib that operates on long doubles).
Edit: In response to the comment, the platform is 'Linux-3.0.0-14-generic-x86_64-with-Ubuntu-11.10-oneiric'. Now, if numpy.float128
has varying precision dependent on the platform, that is also useful knowledge for me!
Just to be clear, it is the precision I am interested in, not the size of an element.
The float128 number type is a very thin wrapper around GCC's __float128 or Intel's _Quad data types and provides an real-number type that is a drop-in replacement for the native C++ floating-point types, but with a 113 bit mantissa, and compatible with FORTRAN's 128-bit QUAD real.
Python's floating-point numbers are usually 64-bit floating-point numbers, nearly equivalent to np.
Python float uses 8 bytes (or 64 bits) to represent real numbers. Unlike the integer type, the float type uses a fixed number of bytes.
np. float is an alias for python float type. np. float32 and np. float64 are numpy specific 32 and 64-bit float types.
numpy.longdouble
refers to whatever type your C compiler calls long double
. Currently, this is the only extended precision floating point type that numpy supports.
On x86-32 and x86-64, this is an 80-bit floating point type. On more exotic systems it may be something else (IIRC on Sparc it's an actual 128-bit IEEE float, and on PPC it's double-double). (It also may depend on what OS and compiler you're using -- e.g. MSVC on Windows doesn't support any kind of extended precision at all.)
Numpy will also export some name like numpy.float96
or numpy.float128
. Which of these names is exported depends on your platform/compiler, but whatever you get always refers to the same underlying type as longdouble
. Also, these names are highly misleading. They do not indicate a 96- or 128-bit IEEE floating point format. Instead, they indicate the number of bits of alignment used by the underlying long double
type. So e.g. on x86-32, long double
is 80 bits, but gets padded up to 96 bits to maintain 32-bit alignment, and numpy calls this float96
. On x86-64, long double
is again the identical 80 bit type, but now it gets padded up to 128 bits to maintain 64-bit alignment, and numpy calls this float128
. There's no extra precision, just extra padding.
Recommendation: ignore the float96
/float128
names, just use numpy.longdouble
. Or better yet stick to doubles unless you have a truly compelling reason. They'll be faster, more portable, etc.
It's quite recommended to use longdouble
instead of float128, since it's quite a mess, ATM. Python will cast it to float64
during initialization.
Inside numpy, it can be a double or a long double. It's defined in npy_common.h
and depends of your platform. I don't know if you can include it out-of-the-box into your source code.
If you don't need performance in this part of your algorithm, a safer way could be to export it to a string and use strold
afterwards.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With