提问人:CoderGuy 提问时间:9/22/2022 更新时间:9/24/2022 访问量:190
双精度(IEEE754双精度 64 位)二进制表示形式
Double (IEEE754 Double precision 64-bit) binary representation
问:
我想将 Java 双精度(IEEE754 双精度 64 位)转换为二进制表示形式,修改 21 个最低有效位以将一些元数据嵌入到双精度中,将其转换回双精度,并保持 6 位小数精度。
约束:我将要处理的双精度值将始终在 [-180, 180] 范围内。
例:
Double value: -145.88160204733163
IEEE754 Double precision 64-bit binary:
1100 0000 0110 0010 0011 1100 0011 0110 0001 0101 0111 1111 0010 1100 0000 1000
IEEE754 Double precision 64-bit binary with 21 least significant bits modified:
1100 0000 0110 0010 0011 1100 0011 0110 0001 0101 0110 0010 1001 1000 0110 0101
Double value with 21 least significant bits modified:
-145.88160199410336
我知道符号需要保持 1 位,指数需要保持 11 位,-180 到 180 之间的整数需要保留 7 位。由于我需要保持 6 位小数位的精度,我认为额外的 24 位有效数字足以保持 6 位小数位的精度(因为每个数字需要 3.32 位,我在这里的理解可能不正确),所以我可以使用 21 位最低有效位来嵌入元数据。
我想知道我在哪里误解了 64 位双精度是如何以二进制表示的,以及是否有任何其他方法可以在不损失所需精度的情况下修改双精度的位。
任何意见都非常感谢!
答:
当 OP 代码更改 IEEE754 双精度 64 位值的 21 个最低有效位时,结果是大于或小于原始值的值。有时,即使只有 1 个最低有效位的变化就足以在打印到 6 个小数位时更改输出。Double
考虑十进制值 ddd.dddddd5,其中数字为 0-9。我们有一个介于两个 ddd.dddddd 值之间的值。该值很少可以精确编码为 *1。使用附近,当打印有 6 位小数时,四舍五入到最接近的 0.000001。输出是 ddd.dddddd 或 0.000001 以上,具体取决于最接近的值是比 ddd.dddddd5 多一点还是少一点。d
Double
Double
Double
如果它打印为 ddd.dddddd,并且有效负载大于原始 21 位 - 即使只是 1 个最低有效位,该值也会多打印 0.000001。同样,如果它打印为 ddd.dddddd + 0.000001 并且有效负载较小,则打印为 dddd.dddddd。
为了实现 OP 的目标,我们可以将值四舍五入到最接近的 0.000001,以使它们远离 ddd.dddddd5 边界。然后,我们可以成功地替换 OP 所描述和推理的至少 21 位。
倒圆角很棘手,因为许多倒圆角技术无法正确处理边缘条件,例如较差的 .这里的问题是并不总是形成一个精确的产品——这对于边缘情况至关重要。round(x*1000000.0)/1000000.0
x * 1000000.0
我不精通 java,但打印到 6 位小数并转换回可以解决问题。Double
请注意,这个答案与我的评论不同。在这种情况下,我专注于不更改值 ddd.ddddddxxxxxx 的数字(如果打印到许多小数位)。正如我现在所看到的,OP 在打印到小数点后 6 位时想要相同的输出。d
*1所有 ,当精确表示时,都具有 0.0、0.5、0.25、0.75、0.125、0.375、0.625、0.875 等小数分数。不是 0.1、0.2、0.3、0.4、0.6、......Double
评论
double x
|x| < 256