Whether assigning of single precision IEEE754 float to double is reversible?

Using the IEEE754 standard, let's assign single precision variable s to double precision variable d and then assign d to single precision variable s'.

Is this operation is reversible (lossless) for any value that can be represented in IEEE754, including NaN, infinity, etc.? In other words, is it guaranteed that s = s' for all possible s?

On my processor NaN is not reversible (01 00 80 7f != 01 00 c0 7f). Brute force shows that NaN is not reversible, but this might be implementation dependent, so please answer within the scope of IEEE754 standard.

• BTW, yes you can store NaN, -inf and +inf in SQLLite: system.data.sqlite.org/index.html/tktview/… – Johan May 3 '16 at 1:01
• @Johan - Thank you! I knew this is the correct place to ask this=) This is workaround for me as my DB (I believe ) has one form of NaN. But there are quiet NaN, signaling NaN. They all map to text 'NaN' =) – Kaponir May 3 '16 at 1:07

Maybe this will help. This is not full answer - just information to think.

5.3 Floating-Point Format Conversions It shall be possible to convert floating-point numbers between all supported formats. If the conversion is to a narrower precision, the result shall be rounded as specified in Section 4. Conversion to a wider precision is exact.

IEEE Std 754-1985

The value of a number does not change when converting a single to a double.
This includes converting single +/-inf to double +/-inf.

However the printed representation of that number may change, this is the way that number would be printed on screen or converted to a string. Let me give you an example.

single s;
single s1;
s = 125.32f;
println("value of s = " + s);  --> displays 125.32
double d = s;
println("value of d = " + d);  --> displays 125.31999969482422

Does that mean that s ≠ d?
No: s does equal d, and when d is assigned to s1, s and s1 will be exactly equal.
The difference in the displayed value is because more digits are needed to uniquely distinguish the argument value from adjacent values of the same type.
This is a quote from the Java docs, but of course this issue extends to all languages that use IEEE754 floats.

Full disclosure: I copied most of this answer from: https://stackoverflow.com/questions/17504833/why-converting-from-float-to-double-changes-the-value

See here if you want to hear it from Jon Skeet himself: https://stackoverflow.com/questions/17504833/why-converting-from-float-to-double-changes-the-value

Update
I just tested the assertion using the following code and I can indeed confirm that casting a single to a double and back again does not yield any data loss whatsoever. This was tested in Delphi, but I have no reason to suspect the results would be different in any other IEEE754 compliant environment.

var
a: cardinal;
s: single absolute a;     //a and s occupy the same memory slot.
s2: single;
b: cardinal absolute s2;  //b and s2 occupy the same memory slot.
d: double;

begin
for a:= 0 to $FFFFFFFF do begin if not(IsNaN(s)) then begin //must exclude NaN to avoid exceptions. d:= s; s2:= d; assert(a = b); end; end; end. The test took 2 minutes of CPU time. Just to satisfy the OP's curiosity there is no 'algorithm' happening here, the line d:= s is compiled as: Project82.dpr.20: d:= s; 00419526 D905CC0E4200 fld dword ptr [$00420ecc]
0041952C DD1DD80E4200     fstp qword ptr [\$00420ed8]

That means the CPU itself performs the cast. And I do believe we can trust the CPU to be IEEE754 compliant.

• Thank you - these topics about "Why text representation differs". I'm wondering "Whether conversion is reversible" and Why. I see JLS says "float to double" is A widening primitive conversion and widening "does not lose information about the overall magnitude of a numeric value" I trust JLS. But Why it happens? I see binary representation of single and double is not just expansion and truncation. Some algorithm of transformation should exist to make s = s' – Kaponir May 3 '16 at 1:44
• Pi is an example where only part of single's mantissa is substring of double representation (01000000010010010000111111011011 and 0100000000001001001000011111101101010100010001000010110100011000). So, reversion is not simple truncation. – Kaponir May 3 '16 at 1:59
• evanw.github.io/float-toy – Kaponir May 3 '16 at 2:02
• @Kaponir, the simple trucation does apply if the extra space is filled with zero's which is what your question was about. If you change the question, then obviously the answer changes as well. If there is non-zero data in the extra space then rounding happens. – Johan May 3 '16 at 2:02
• 23-th (least significant) of mantissa's bit of single is 1 and 0 in double – Kaponir May 3 '16 at 2:07

Quite funny, I wasn't able to find the IEEE 754 document that describes the standard. I guess that such conversions are not part of the "formal" standard, and they are left to the implementation (I may be wrong here).

Information-wise, there is no reason to lose information by the conversion 32bit->64bit->32bit. If performed correctly, the conversion should return exactly the original value.

Checking a few edge cases (using the calculators of http://babbage.cs.qc.cuny.edu/IEEE-754.old/64bit.html) show this is indeed the case. It shouldn't be too difficult to write a program that goes over all the 32bit values and verifies they convert back correctly. Ignoring the NaNs, this shouldn't even take that long.

• Kahan played important role in creation of the standard. here is his paper cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF yes - it has no more then 2^32 states. – Kaponir May 3 '16 at 1:50
• @Kaponir, how exactly would you go about storing more than 2^32 states in a 4 byte variable :=? – Johan May 3 '16 at 2:07
• i'm not going to store more then 2^32 states. – Kaponir May 3 '16 at 2:09
• @Kaponir thanks, I saw this paper - but this is "lecture notes" and not the final standard, right? – Ran G. May 3 '16 at 2:36
• @Ran G. right - I just have no anything better. – Kaponir May 3 '16 at 3:31