JavaScript 浮点数未正确截断

JavaScript float not truncating correctly

提问人:Alexander Veheecke 提问时间:9/8/2022 最后编辑:E_net4Alexander Veheecke 更新时间:9/10/2022 访问量:36

问:

我正在努力让浮点数正确显示。它在大多数情况下都有效。例如,如果我在“kWh”中输入 0.2,在“使用小时数”中输入 0.04,则在“总计”中输出 0.008。但是,当我将这些值更改为 0.02 和 0.23 时,它会输出 0.0460000000000000006。为什么不输出 0.046?我在这里错过了什么?

<script>
        function calculate(){
            var amount = document.getElementById("kW").value;
            var amount = parseFloat(amount).toFixed(2);
            var quantity = document.getElementById("hours").value;
            var quantity = parseFloat(quantity).toFixed(2);
            var total = amount * quantity;
            document.getElementById("total").value = total;
        }
    </script>
<div class="kWattsCol">
                <p><b>kWh</b></p>
                <input type="number" oninput="calculate()" id="kW" required>
            </div>

            <div class="hoursCol">
                <p><b>Hours used</b></p>
                <input type="number" oninput="calculate()" id="hours"required>
            </div>

            <div class="totalCol">
                <p><b>Total</b></p>
                <input type="text" id="total" readonly>
            </div>

JavaScript 浮点 精度

评论

0赞 Eric Postpischil 9/8/2022
@Quentin:请不要将浮点问题混淆为该问题的重复项。这个问题涉及格式化浮点数以供显示的问题,这是一种语言选择(使用默认值时),并不是严格意义上的浮点运算属性。
0赞 Sam Mason 9/9/2022
@EricPostpischil问题已经重新打开,你想放一个漂亮的解释器吗?
0赞 E_net4 9/9/2022
这回答了你的问题吗?JavaScript 如何确定格式化浮点值时要生成的位数?

答:

1赞 Eric Postpischil 9/10/2022 #1

校正

...当我将这些值更改为 0.02 和 0.23 时,它输出 0.0460000000000000006...

这些浮点积将是接近 .0046 的数字,而不是接近 .046 的数字。所以我怀疑实际输入是“0.2”和“0.23”。下面的答案就是在此基础上进行的。

讨论

当使用默认的数字 JavaScript 格式时,它会生成足够多的有效数字,以便以浮点格式唯一区分浮点数与其相邻数。这个答案进一步描述了这一点。

当输入“0.2”转换为 JavaScript 使用的浮点格式(IEEE-754 binary64,也称为“双精度”)时,结果为 0.2000000000000000011102230246251565404236316680908203125。转换“0.04”时,结果为0.040000000000000000832667268468867405317723751068115234375。当这些相乘时,结果为 0.0080000000000000000166533453693773481063544750213623046875。(这包括将实数算术乘积舍入到以浮点格式表示的最接近的值。

以下是结果前的邻居、结果和结果后的邻居:

0.00799999999999999843180997771696638665162026882171630859375
0.008000000000000000166533453693773481063544750213623046875
0.00800000000000000190125692967058057547546923160552978515625

观察到 .008 最接近其中的中间,即算术结果。这意味着,当 0.0080000000000000000166533453693773481063544750213623046875 被格式化为显示时,我们只需要生成“0.008”来识别它。

在第二种情况下,转换“0.23”得到 0.230000000000000000099920072216264088638126850128173828125,则乘积为 0.0460000000000000006161737786669618799351155757904052734375。

看看之前的邻居、结果和之后的邻居,我们有:

0.04599999999999999922284388276239042170345783233642578125
0.046000000000000006161737786669618799351155757904052734375
0.0460000000000000131006316905768471769988536834716796875

观察到 .046 更接近之前的邻居,而不是结果;它在小数点后第十九位相差不到 1,而结果相差超过 6。因此,为了确定结果,我们需要生成“0.0460000000000000006”。

评论

0赞 Sam Mason 9/11/2022
谢谢!希望能被其他人联系起来