假设我有一个十六进制数字“4072508200000000”,并且我希望将它表示的IEEE-754 double 格式的浮点数(293.03173828125000)放入JavaScript变量中。
我可以想到一种使用一些 mask 和对pow()的调用的方法,但是有没有更简单的解决方案?
需要客户端解决方案。
这可能会有所帮助。该网站可让您输入IEEE-754的十六进制编码并获得尾数和指数的分析结果。
http://babbage.cs.qc.edu/IEEE-754/64bit.html
因为人们总是会问“为什么?”,这是为什么:我正在尝试填写Google的Procol Buffers(protobuf)的现有但不完整的实现。
最佳答案
我不知道有什么好办法。当然可以用困难的方式完成,这是完全在JavaScript中的一个单精度示例:
js> a = 0x41973333
1100428083
js> (a & 0x7fffff | 0x800000) * 1.0 / Math.pow(2,23) * Math.pow(2, ((a>>23 & 0xff) - 127))
18.899999618530273
生产实现应考虑到大多数字段具有魔术值,通常通过为最大或最小指定特殊解释来实现。因此,请检测
NaN
和无穷大。上面的例子应该检查底片。 (a和0x80000000)更新:好的,我也有加倍的。您不能直接扩展上述技术,因为内部JS表示形式是 double 的,因此根据其定义,它最多只能处理长度为52的位字符串,并且移位最多不能超过32。
好吧,要做一倍,首先要砍掉一个低8位或32位的字符串;用一个单独的对象处理它们。然后:
js> a = 0x40725082
1081233538
js> (a & 0xfffff | 0x100000) * 1.0 / Math.pow(2, 52 - 32) * Math.pow(2, ((a >> 52 - 32 & 0x7ff) - 1023))
293.03173828125
js>
我保留上面的示例,因为它来自OP。最困难的情况是低32位有一个值。这是0x40725082deadbeef的转换,是全精度的double:
js> a = 0x40725082
1081233538
js> b = 0xdeadbeef
3735928559
js> e = (a >> 52 - 32 & 0x7ff) - 1023
8
js> (a & 0xfffff | 0x100000) * 1.0 / Math.pow(2,52-32) * Math.pow(2, e) +
b * 1.0 / Math.pow(2, 52) * Math.pow(2, e)
293.0319506442019
js>
您可以考虑一些明显的子表达式,但我已经将其保留下来,以便您了解它与格式的关系。