JVM/CLR上相同字节的不同浮点值

Eri*_* W. 1 java vb.net floating-point clr jvm

我正在将最初用VB.NET编写的程序移植到Java.我正在读取一个以小端序存储32位浮点数的文件.

原始程序执行此操作:

Dim br As BinaryReader = ...
Dim f_vb As Single = br.ReadSingle
Run Code Online (Sandbox Code Playgroud)

Java是大端,所以我在转换为float之前反转字节.

RandomAccessFile raf = // ...
int i = raf.readInt();
int bigEndian = Integer.reverseBytes(i);
float f_java = Float.intBitsToFloat(bigEndian);
Run Code Online (Sandbox Code Playgroud)

据我所知,f_vbf_java包含相同的位.也就是说,BitConverter.ToInt32on f_vbFloat.floatToIntBits(和floatToRawIntBits)on f_java给出相同的东西.但是,花车并不相同.例如,让我们bigEndian == 0x4969F52F.Java将报告958290.94,VB.NET将报告958290.938.我猜这是因为JVM和CLR处理浮点数的方式有所不同,但我对浮点问题知之甚少以找出原因.这种精度的损失导致了线路故障,所以我想确定来源.

Eri*_*hil 6

这些位表示的确切值是958290.9375.可能是你用来显示Java中的值,显示"958290.94",默认情况下舍入到两位小数或八位有效数字,以及你在VB.NET中使用的任何显示"958290.938"的值,默认情况下舍入小数点后三位或九位有效数字.或者,其中一个可能很难将浮点数转换为十进制以进行显示.

如果有选项可以显示更多数字,请尝试使用它们.或者,构造值958290.9375,从f_java中减去它,并测试结果是否正好为零.它应该是.

最接近958290.9375的单精度浮点数是958290.875和958291.任何一个中等格式的格式化程序都不能显示为"958290.94"或"958290.938",所以你拥有的浮点数不太可能是958290.9375.