Why does converting in and out of LongBits introduce error?

5 vues (au cours des 30 derniers jours)
Alec Jacobson
Alec Jacobson le 25 Nov 2022
Réponse apportée : Aditya le 28 Nov 2022
In Java,
double value = 0.007168281523489443;
double res = java.lang.Double.longBitsToDouble(java.lang.Double.doubleToLongBits(value));
System.out.println(value==res);
prints true
But the same thing in matlab,
value = 0.007168281523489443;
res = java.lang.Double.longBitsToDouble(java.lang.Double.doubleToLongBits(value));
res == value
shows
ans =
logical
0
I noticed that class(java.lang.Double.doubleToLongBits(value)) is 'double'. I would have thought it would be uint64. Could this be related?
  1 commentaire
Alec Jacobson
Alec Jacobson le 25 Nov 2022
FWIW,
typecast(typecast(value,'uint64'),'double') == value
works

Connectez-vous pour commenter.

Réponses (1)

Aditya
Aditya le 28 Nov 2022
Hi,
I understand that you are using java.long.Double to convert a double to its IEEE-754 representation as long and the long representation back to a double. Finally, you are comparing both the doubles to check if they are equal or not. When using Java, the equality is true but when calling the same functions from MATLAB, the equality results in a false.
If a Java method returns a primitive type, MATLAB converts the type. When a long is retuned from a Java method, it is converted to a double’. You can read more about it at Handle Data Returned from Java Methods - MATLAB & Simulink (mathworks.com).
So, when java.lang.Double.doubleToLongBits is called, its returned ‘long’ value is converted to a ‘double.’ This ‘double’ value, when passed to java.lang.Double.longBitsToDouble, will again be converted to a long.’ During these two conversions, there is a loss of information which leads equality comparison resulting in false. Equivalent Java code for MATLAB calls would be something like this:
double original_double = 0.007168281523489443;
long original_long = java.lang.Double.doubleToLongBits(original_double);
double long_to_double = (double)original_long;
long double_to_long = (long) long_to_double;
System.out.println(String.format("Original long representation: 0x%08X", original_long));
System.out.println(String.format("Representation after two conversions: 0x%08X", double_to_long));
double converted = java.lang.Double.longBitsToDouble(double_to_long);
boolean comparison = converted == original_double;
System.out.println("Comparing original and converted: " + comparison);
You can see that the comparison evaluates to a false in the output of above code:
Original long representation: 0x3F7D5C7CEB63F9DE
Representation after two conversions: 0x3F7D5C7CEB63FA00
Comparing original and converted: false
Also notice the difference is representation of long and a two-times converted long (long to double to long).
Therefore, when comparing floating points, instead of using ‘==,’ you should always use a small tolerance as shown here. The value of tolerance would depend on your use case.

Catégories

En savoir plus sur Mathematics dans Help Center et File Exchange

Tags

Produits


Version

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by