long double != double !?

Status
Not open for further replies.

Joegi

Well-known member
I read somewhere that "long double" = "double" (on Teensy LC/3.x), but the following code shows that "1.23L" != "(double)1.23" (at least regarding implicit type casting)!(?)
Code:
void setup() {
  Serial.begin(9600);
  while(!Serial);
}
void loop() {
double y;

  y = 1.23L / 4.56;
  Serial.println(y, 16);
  y = (double)1.23 / 4.56;
  Serial.println(y, 16);while(1);
}
 
Last edited:
This is due to Teensy using the option '-fsingle-precision-constant', in which the compiler is told to treat all non-suffixed floating point constants as single precision.

The rationale for this is the Teensy 3.5/3.6 having single precision floating point support in hardware, but not double precision.

So without the switch '-fsingle-precision-constant', the following code:
Code:
float f, g;

   // ...

f = g + 1.0;

would convert g to double precision, call the floating point emulation routine to add 1.0, and then convert the result back to f.

Now, there are processors where long double is a different type than double, such as the x86_64 and the PowerPC, but so far the arm microprocessors do not add a wider type.
 
Now, there are processors where long double is a different type than double, such as the x86_64 and the PowerPC, but so far the arm microprocessors do not add a wider type.
They are different types on Teensy as well, but they are the same size. This does matter for overload resolution and aliasing (e.g. casting a "long double*" to a "double*" is not safe).

Code:
#include <type_traits>

void setup() {
    static_assert(std::is_same<double, long double>::value, "different types");
}

void loop() {}
test_long_double:4: error: static assertion failed: different types
static_assert(std::is_same<double, long double>::value, "different types");

^
 
Hm, but why is "double x = 10.0L / 2.4;" != "double x = 10.0 / 2.4L;"?

Because in binary floating point 2.4 cannot be represented, while 10.0 can be represented. Since the 2.4 does not have a suffix, the compiler creates it as a single precision constant due to the '-fsingle-precision-constant' option that Teensy uses. So it truncates the value to 32-bit floating point. Then when it calculates, '10.0L / 2.4', it converts the 32-bit binary floating point 2.4 to long double, does that calculation in long double, and then logically converts the long double value to double.
 
...does that calculation in long double, and then logically converts the long double value to double.

But if "long double" equals "double" (at least regarding size) there would be no difference between a "long double" calculation and a "double" calculation and then also no conversion from "long double" to "double" would be necessary (at least regarding precision)!?

And why can "10.0" be represented in "float", but "2.4" cannot? I learned that "float" has 7 digits of precision and "2.4" has two digits.
 
But if "long double" equals "double" (at least regarding size) there would be no difference between a "long double" calculation and a "double" calculation and then also no conversion from "long double" to "double" would be necessary (at least regarding precision)!?

And why can "10.0" be represented in "float", but "2.4" cannot? I learned that "float" has 7 digits of precision and "2.4" has two digits.
I used 'logical' to mean that even though no actual conversion takes place, internally within the compiler things are represented by the type, and a logical conversion takes place.

Binary floating point is not represented as decimal digits. Instead it is a BINARY mantissa with a BINARY exponent. So you can represent things like 1.5 precisely in binary floating point because you are dividing by a power of two. Here is one site that describes the format: http://steve.hollasch.net/cgindex/coding/ieeefloat.html
 
Last edited:
I used 'logical' to mean that even though no actual conversion takes place, internally within the compiler things are represented by the type, and a logical conversion takes place.

Binary floating point is not represented as decimal digits. Instead it is a BINARY mantissa with a BINARY exponent. So you can represent things like 1.5 precisely in binary floating point because you are dividing by a power of two. Here is one site that describes the format: http://steve.hollasch.net/cgindex/coding/ieeefloat.html

Thanks! I should have dealt with the internal representation of floating point values before asking here!
 
Status
Not open for further replies.
Back
Top