【发布时间】:2011-03-07 00:21:42
【问题描述】:
在 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% 正确,但它似乎足够好。 (我仍在寻找现有的实现)。
【问题讨论】:
-
我很想知道您为什么要转换为 IEEE 单精度表示。 Javascript 数字不是通常存储为双精度(64 位)数量吗?
-
您正在为小值返回无穷大 (
exponent < -126);不知何故,我不认为那是你想要的。 (此外,-0.0 会以错误的符号位结束,但这可能对您的应用程序无关紧要。) -
Mark Dickinson:我正在转换为 32 位 IEEE,因为应用程序将生成一些将在内存编辑器中使用的值(适用于地址 + 字节格式)。根据维基百科,“指数
-
关于指数:输入可以是任何有效的 IEEE 754 双精度值;使用您当前的代码,如果您的输入像 1e-60 这样很小,您最终会输出无穷大的二进制表示。改为输出 0.0 的表示可能更合适,这是通过将双精度值四舍五入为单精度自然得到的。为了区分 0.0 和 -0.0,我知道的唯一方法是查看
atan2(flt, -1.0)的结果(如果 JavaScript 提供了 copysign,那将是更好的方法)。 -
你可以用类型化数组来做到这一点:stackoverflow.com/a/10564792/309483
标签: javascript binary floating-point ieee-754