0

I am struggling to get the float number to show correctly. It works for the most part. For example, if I input 0.2 in "kWh" and 0.04 in "Hours used", it outputs 0.008 in "Total. However, when I change these values to 0.02 and 0.23, it outputs 0.046000000000000006. Why doesn't it output 0.046 instead? What am I missing here?

<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>
E_net4
  • 27,810
  • 13
  • 101
  • 139
  • @Quentin: Please do not promiscuously close floating-point questions as duplicates of [that question](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). This question involves issues of formatting floating-point numbers for display, which is a language choice (when defaults are used), and is not strictly a property of floating-point arithmetic. – Eric Postpischil Sep 08 '22 at 11:44
  • @EricPostpischil question has been reopened, do you want to put a nice explainer in? – Sam Mason Sep 09 '22 at 08:40
  • Does this answer your question? [How does JavaScript determine the number of digits to produce when formatting floating-point values?](https://stackoverflow.com/questions/49384477/how-does-javascript-determine-the-number-of-digits-to-produce-when-formatting-fl) – E_net4 Sep 09 '22 at 09:07
  • @SamMason: Done. – Eric Postpischil Sep 09 '22 at 19:23

1 Answers1

1

Correction

… when I change these values to 0.02 and 0.23, it outputs 0.046000000000000006…

The floating-point product of these would be a number near .0046, not near .046. So I suspect the actual input was “0.2” and “0.23”. The answer below proceeds on this basis.

Discussion

When default JavaScript formatting of numbers is used, it produces just enough significant digits to uniquely distinguish the floating-point number from its neighbors in the floating-point format. This answer describes this further.

When the input “0.2” is converted to the floating-point format JavaScript uses (IEEE-754 binary64, also called “double precision”), the result is 0.200000000000000011102230246251565404236316680908203125. When “0.04” is converted, the result is 0.040000000000000000832667268468867405317723751068115234375. When these are multiplied, the result is 0.008000000000000000166533453693773481063544750213623046875. (This includes rounding of the real-number-arithmetic product to the nearest value representable in the floating-point format.)

Here is the neighbor before the result, the result, and the neighbor after the result:

0.00799999999999999843180997771696638665162026882171630859375
0.008000000000000000166533453693773481063544750213623046875
0.00800000000000000190125692967058057547546923160552978515625

Observe that .008 is closest to the middle of these, the arithmetic result. That means, when 0.008000000000000000166533453693773481063544750213623046875 is formatted for display, we only need to produce “0.008” to identify it.

In the second case, converting “0.23” yields 0.2300000000000000099920072216264088638126850128173828125, and then the product is 0.046000000000000006161737786669618799351155757904052734375.

Looking at the neighbor before, the result, and the neighbor after, we have:

0.04599999999999999922284388276239042170345783233642578125
0.046000000000000006161737786669618799351155757904052734375
0.0460000000000000131006316905768471769988536834716796875

Observe that .046 is closer to the neighbor before rather than to the result; it differs by less than one in the nineteenth decimal place, whereas the result differs by more than 6. Therefore, to identify the result, we need to produce “0.046000000000000006”.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312