javascript从/到位浮动

Posted

技术标签:

【中文标题】javascript从/到位浮动【英文标题】:javascript float from/to bits 【发布时间】:2011-01-01 11:43:42 【问题描述】:

我正在尝试用任何其他语言而不是 javascript 执行一些简单的脑死操作:从浮点数中取出位(反之亦然)。

在 C/C++ 中是这样的

浮点数 = 3.1415; int b = *((int*)&a);

反之亦然

int a = 1000; 浮动 b = *((float*)&a);

在 C# 中,您可以使用 BitConverter ...floatBits 或 Java 中的类似内容...即使在 VB6 中,看在上帝的份上,您也可以将 float32 存储到 int32 中。我到底该如何在javascript中的int和float之间进行翻译?

【问题讨论】:

嘿,只是想说谢谢你回答我的问题。我需要知道如何在 C++ 中进行浮点/整数转换; 备注:像这样强制转换指针违反了 C++ 中严格的别名规则。你必须使用 memcpy。 这能回答你的问题吗? Read/Write bytes of float in JS 【参考方案1】:
function DoubleToIEEE(f)

    var buf = new ArrayBuffer(8);
    (new Float64Array(buf))[0] = f;
    return [ (new Uint32Array(buf))[0] ,(new Uint32Array(buf))[1] ];

【讨论】:

而到另一个方向(从字节到浮点数),请参阅:***.com/a/21282715/1691517。 如果有人要转换为二进制表示字符串:const DoubleToBinaryString = (x) => DoubleToIEEE(x).reverse().map(p => p.toString(2).padStart(32, '0')).join('');【参考方案2】:

你当然不会在 JavaScript 中得到任何低级的东西。允许以一种必须对不受信任的潜在攻击者网站安全使用的语言进行重铸和指针攻击是极其危险的。

如果您想在 Number 中获得单精度值的 32 位 IEEE754 表示(记住也不是 int;您在 JavaScript 中获得的唯一数字类型是 double),您必须通过将符号、指数和尾数位一起摆弄来自己制作。有示例代码here。

【讨论】:

刚刚查看了 babbage.cs.qc.edu 站点中的 Javascript -- 它可能会产生正确的答案,并且可能在在线计算器上运行良好,但它的编写很糟糕且不适合在我看来重用。 我不明白为什么向 JavaScript 数字添加本机 IEEE 二进制格式转换会是一个安全问题。这件事不涉及重铸或指针。 @akauppi 没有安全问题。只不过允许使用 Uint8Array、Uint16Array 等来获得连续的内存所有权。只需要有一个 Float32 对象并给它一个本地方法 toUint8Array。它将比当今可用的替代方案更有效。由于 javascript 中的所有数字都类似于包装在变体中的双精度数,因此这样做的成本基本上是创建 Number 内部表示字节的 uint8array 变体,并将该数量的字节从数字的内部存储到 uint8array 的内部存储器。跨度> 链接好像坏了。也许您想将示例代码添加到答案中? (来自Help Center > Answering > How do I write a good answer?:“始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。”)【参考方案3】:
function FloatToIEEE(f)

    var buf = new ArrayBuffer(4);
    (new Float32Array(buf))[0] = f;
    return (new Uint32Array(buf))[0];

不幸的是,这不适用于双打和旧浏览器。

【讨论】:

【参考方案4】:
    JavaScript 使用 double (IEEE 754) 来表示所有数字 double 由 [sign, exponent(11bit), mantissa(52bit)] 字段组成。 数字的值使用公式(-1)^sign * (1.mantissa) * 2^(exponent - 1023) 计算。 (1.mantissa - 意味着我们将尾数位加 1 在开头并将该值作为数字,例如,如果尾数 = 101 我们得到数字 1.101 (bin) = 1 + 1/2 + 1/8 (dec) = 1.625 (dec)。 如果数字大于零,我们可以得到sign位测试的值。这里0 有一个小问题,因为double+0-0 值,但是我们可以通过计算1/value 并检查值是+Inf 还是-Inf 来区分这两个。李> 由于1 <= 1.mantissa < 2 我们可以使用Math.log2 获得指数值,例如Math.floor(Math.log2(666.0)) = 9 所以指数是 exponent - 1023 = 9exponent = 1032,二进制是 (1032).toString(2) = "10000001000" 获得指数后,我们可以将数字缩放到零指数,而无需更改尾数value = value / Math.pow(2, Math.floor(Math.log2(666.0))),现在值代表数字(-1)^sign * (1.mantissa)。如果我们忽略符号并将其乘以2^52,我们会得到与 1.mantissa 具有相同位的整数值:((666 / Math.pow(2, Math.floor(Math.log2(666)))) * Math.pow(2, 52)).toString(2) = "10100110100000000000000000000000000000000000000000000"(我们必须忽略前导 1)。 经过一些字符串连接后,你会得到你想要的

这只是概念证明,我们没有讨论非规范化数字或 NaN 等特殊值 - 但我认为它也可以扩展以解决这些情况。

@bensiu 的回答很好,但是如果发现自己使用一些旧的 JS 解释器,你可以使用这种方法。

【讨论】:

【参考方案5】:

就像其他发帖人所说的那样,JavaScript 是松散类型的,因此从浮点到 int 的数据类型没有区别,反之亦然。

但是,您正在寻找的是

浮点到整数:

Math.floor( 3.9 ); // result: 3 (truncate everything past .) or
Math.round( 3.9 ); // result: 4 (round to nearest whole number)

取决于你想要的。在 C/C++ 中,它本质上是使用 Math.floor 从浮点数转换为整数。

int 浮动:

var a = 10;
a.toFixed( 3 ); // result: 10.000

【讨论】:

这不是他想要的。他正在寻找双精度数的二进制表示。问题中的 '(int*)&a' 给出了一个指向双精度的机器级 (IEEE) 位的指针。

以上是关于javascript从/到位浮动的主要内容,如果未能解决你的问题,请参考以下文章

JavaScrip笔记心得(持续更新)

JavaScrip笔记心得(持续更新)

JavaScrip笔记心得(持续更新)

JavaScrip book

JavaScrip入门

JavaScrip和Java一样吗?