如何在 Javascript 中将浮点数转换为其二进制表示形式(IEEE 754)?
在 Javascript 中将浮点数转换为其二进制表示形式的最简单方法是什么? (例如1.0 -> 0x3F800000)。
我尝试手动执行此操作,这在某种程度上有效(对于通常的数字),但对于非常大或非常小的数字(没有范围检查)以及特殊情况(NaN、无穷大等),它会失败:
function floatToNumber(flt)
{
var sign = (flt < 0) ? 1 : 0;
flt = Math.abs(flt);
var exponent = Math.floor(Math.log(flt) / Math.LN2);
var mantissa = flt / Math.pow(2, exponent);
return (sign << 31) | ((exponent + 127) << 23) | ((mantissa * Math.pow(2, 23)) & 0x7FFFFF);
}
我是吗重新发明轮子?
编辑:我改进了我的版本,现在它可以处理特殊情况。
function assembleFloat(sign, exponent, mantissa)
{
return (sign << 31) | (exponent << 23) | (mantissa);
}
function floatToNumber(flt)
{
if (isNaN(flt)) // Special case: NaN
return assembleFloat(0, 0xFF, 0x1337); // Mantissa is nonzero for NaN
var sign = (flt < 0) ? 1 : 0;
flt = Math.abs(flt);
if (flt == 0.0) // Special case: +-0
return assembleFloat(sign, 0, 0);
var exponent = Math.floor(Math.log(flt) / Math.LN2);
if (exponent > 127 || exponent < -126) // Special case: +-Infinity (and huge numbers)
return assembleFloat(sign, 0xFF, 0); // Mantissa is zero for +-Infinity
var mantissa = flt / Math.pow(2, exponent);
return assembleFloat(sign, exponent + 127, (mantissa * Math.pow(2, 23)) & 0x7FFFFF);
}
我仍然不确定这是否 100% 正确,但它似乎工作得足够好。 (我仍在寻找现有的实现)。
What's the easiest way to convert a floating point number to its binary representation in Javascript? (e.g. 1.0 -> 0x3F800000).
I have tried to do it manually, and this works to some extent (with usual numbers), but it fails for very big or very small numbers (no range checking) and for special cases (NaN, infinity, etc.):
function floatToNumber(flt)
{
var sign = (flt < 0) ? 1 : 0;
flt = Math.abs(flt);
var exponent = Math.floor(Math.log(flt) / Math.LN2);
var mantissa = flt / Math.pow(2, exponent);
return (sign << 31) | ((exponent + 127) << 23) | ((mantissa * Math.pow(2, 23)) & 0x7FFFFF);
}
Am I reinventing the wheel?
EDIT: I've improved my version, now it handles special cases.
function assembleFloat(sign, exponent, mantissa)
{
return (sign << 31) | (exponent << 23) | (mantissa);
}
function floatToNumber(flt)
{
if (isNaN(flt)) // Special case: NaN
return assembleFloat(0, 0xFF, 0x1337); // Mantissa is nonzero for NaN
var sign = (flt < 0) ? 1 : 0;
flt = Math.abs(flt);
if (flt == 0.0) // Special case: +-0
return assembleFloat(sign, 0, 0);
var exponent = Math.floor(Math.log(flt) / Math.LN2);
if (exponent > 127 || exponent < -126) // Special case: +-Infinity (and huge numbers)
return assembleFloat(sign, 0xFF, 0); // Mantissa is zero for +-Infinity
var mantissa = flt / Math.pow(2, exponent);
return assembleFloat(sign, exponent + 127, (mantissa * Math.pow(2, 23)) & 0x7FFFFF);
}
I'm still not sure if this works 100% correctly, but it seems to work good enough.
(I'm still looking for existing implementations).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
新技术使这一切变得简单,而且可能也更具前向兼容性。我喜欢扩展内置原型,但不是每个人都喜欢。因此,请随意将以下代码修改为经典的过程方法:
测试:
new technologies are making this easy and probably also more forward-compatible. I love extending built in prototypes, not everyone does. So feel free to modify following code to classical procedural approach:
Test:
这是一个适用于我测试过的所有内容的函数,但它不区分 -0.0 和 +0.0。
它基于 http://jsfromhell.com/classes/binary-parser 的代码,但它是专门用于 32 位浮点数并返回整数而不是字符串。我还对其进行了修改,使其更快且(稍微)更具可读性。
Here's a function that works on everything I've tested it on, except it doesn't distinguish -0.0 and +0.0.
It's based on code from http://jsfromhell.com/classes/binary-parser, but it's specialized for 32-bit floats and returns an integer instead of a string. I also modified it to make it faster and (slightly) more readable.