Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java DataView getFloat32返回不正确但近似的数字_Java_Javascript_Floating Point_Bytearray - Fatal编程技术网

Java DataView getFloat32返回不正确但近似的数字

Java DataView getFloat32返回不正确但近似的数字,java,javascript,floating-point,bytearray,Java,Javascript,Floating Point,Bytearray,我在java服务器(jetty)上使用WebSocket以字节的形式发送值(浮点数),在javascript代码中使用DataView.getFloat32(从ArrayBuffer创建)提取它们 我的问题是数字似乎不正确(但几乎等于实际值),例如: 如果我发送2.43,在javascript中它输出2.4300000667522,或者在其他情况下,类似于2.439999340243 在java中,我使用ByteBuffer: byte[] numberBytes = ByteBuffer.al

我在java服务器(jetty)上使用WebSocket以字节的形式发送值(浮点数),在javascript代码中使用DataView.getFloat32(从ArrayBuffer创建)提取它们

我的问题是数字似乎不正确(但几乎等于实际值),例如:

如果我发送2.43,在javascript中它输出2.4300000667522,或者在其他情况下,类似于2.439999340243

在java中,我使用ByteBuffer:

byte[] numberBytes = ByteBuffer.allocate(4).putFloat(number).array();
getFloat方法的输出是正确的:

number = ByteBuffer.wrap(numberBytes).getFloat(); //returns 2.43
有人知道为什么会这样吗

编辑:
关于浮点精度,我的问题是,如果我使用double,这将意味着我的应用程序的通信量将增加一倍-我需要发送50-100个数字的包,每秒至少发送10-15次,对于大量客户机也是如此。

它来自64位的Javascript浮点数。请参阅,这不是Javascript/Java主题,但解释了为什么浮点数不精确。 在您的情况下,如果执行简单的
Java
测试:

float f = 2.43f;
double d = (double)f;
System.out.println("as float: "+f+", as double: "+ d);
您将获得:

as float: 2.43, as double: 2.430000066757202

如果精度对您的应用程序很重要,请尝试与两侧的
双值
兼容,或使用带有刻度或精度附加信息的
整数
值,例如,使用
整数=243而不是
单位数=2.43f
;int标度=100

问题在于浮点数的表示,而不是getFloat32()函数。在我的例子中,因为我需要以5的精度工作,所以我使用了number.toFixed(5),在将数字显示为字符串时,我应该使用.toPrecision(5)。

这个问题是由于DataView.getFloat32()是懒惰的

您所期望的是,ArrayBuffer中的二进制数据应该以浮点形式读取,它有足够的尾数位来满足6~9位的精度,因此当它被视为十进制数时,它会被舍入,然后该值被分配给一个双精度变量。因为这些浮点数和双精度数在尾数中具有不同的位以获得不同的精度,所以在表示完全相同的十进制数时,可以预期完全不同的尾数。(我们一直在谈论十进制数,没有人用浮点数来表示二进制数。另请参见)

例如,浮点数中的2.43是
0x401B851F
,双精度中的2.43是
0x400370A3D70A3D71
。您只需观察十六进制表示,就可以看到它有完全不同的尾数

但是,在中看到的getFloat32()的实现与T.Gournelle的回答中描述的完全相同。DATAView。GETFLUAT32()调用StUnDouple(),它将双参数作为参数,因此,将一个隐式C++浮点转换从浮点转换为双。C++转换使双值等价于浮点二进制值,而不是其十进制值。 所以当你得到2.4300000066757202的双倍时,那就是
0x400370a3e000000
。你看到双精度尾数末尾的
0000000
?这就是getFloat32()的懒惰,它只需执行一个C float来进行双重转换,而不是实际获取浮点值

所有这一切意味着,在执行getFloat32()之后,您必须自己采取额外的步骤,舍入到6或7位数


(注意:我将此作为一个单独的回答,因为T.Gounelle的回答给出了浮点精度的背景,但实际上没有回答OP关于getFloat32导致精度错误的问题。)

几乎每个人都知道为什么会发生这种情况。阅读“浮点数”的含义。我知道它是关于浮点表示的,32位精度可能会导致这种行为,但我认为javascript的getFloat32()函数会解决这个问题(近似正确):我不理解的是java代码为什么工作?number=ByteBuffer.wrap(numberBytes.getFloat();System.out.println(“编号:”+编号)//这是正确打印的,不是2.4300000667522这只是数字的打印方式。请看规则。谢谢你的提示。因为我只需要在客户端表示数字,所以在javascript中,我发现当需要给定精度(在我的例子中是5位小数)时,将浮点数显示为字符串的正确方法是使用number.toPrecision(…)函数。问题是,如果我使用double,对于我的应用程序来说,这意味着双流量。我需要发送50-100个数字的包裹,每秒10-15次,所以我在这里有点挣扎。。。那么还有其他选择吗?一种选择是发送无符号整数(32位)并按10000进行缩放(因为我需要5位小数的精度)。这意味着我能发送的实际最大数字是42949.67296,对吗?取决于你的数字范围,整数可能是个不错的选择。额外的
标度
可以在数字之间共享,从而减少开销。范围是多少?嗯,10000应该是最大值,但我现在不确定(可能是100000,这不起作用)。但是,难道没有一种近似方法/算法可以适合这种情况吗?我试图固定(5),但对于269.02输出269.01999(显然是从269.0199890136719),我遇到了,这解释了理性。看起来真的很好,广告上说要为32位浮点和64位工作。不过我还没有测试。