JavaScript浮点数相加问题:分数赋值变量求和是否必为1?
Great question—this cuts straight to how JavaScript handles floating-point math, and the subtle differences between using computed fractions vs. decimal literals. Let’s break this down clearly:
First: How JavaScript stores numbers
No matter if you write 1/2 or 0.5, JavaScript stores the result as an IEEE 754 double-precision floating-point number. This format can exactly represent fractions that are powers of 1/2 (like 1/2, 1/4, 1/8, etc.), but it can’t represent infinite binary fractions (like 1/3, 1/10) exactly—those get stored as the closest possible approximate value.
Your specific variables: Let’s crunch the numbers
Let’s look at each variable’s actual stored value:
a = 1/2: This is exactly0.5(a power of 1/2), so it’s stored perfectly.b = 1/3: This is an infinite binary fraction, so JS stores it as0.3333333333333333—the closest possible double-precision value to 1/3.c = 1/12andd = 1/12: Each becomes0.08333333333333333, the closest approximation to 1/12.e = 0: Exactly stored.
Now let’s add them up:0.5 + 0.3333333333333333 + 0.08333333333333333 + 0.08333333333333333
If you calculate the approximate values:0.3333333333333333 + 0.08333333333333333 * 2 = 0.3333333333333333 + 0.16666666666666666 = 0.5
Adding that to a’s 0.5 gives exactly 1.0.
Wait—so why does this work, even though 1/3 and 1/12 are approximations? Because the sum of those approximations happens to land exactly on a value that can be represented perfectly as a double-precision float. It’s a happy coincidence of how the rounding works for these specific numbers.
Comparing fraction assignments vs. decimal literals
Let’s clarify the difference you asked about:
- For fractions that are exact in binary (like 1/2, 1/4):
1/2and0.5are identical. JS computes1/2to exactly0.5, so the variable holds the same value either way. - For non-exact fractions (like 1/3):
1/3gives you the closest possible double-precision value to the true 1/3.- If you write a decimal literal like
0.333, that’s a different (less accurate) approximation than1/3—so the variable will hold a different value. - If you write the exact approximate value that
1/3produces (0.3333333333333333), then it’s identical to using1/3.
So, does your sum always equal 1?
In this specific case? Yes—every time you run this code in a standards-compliant JavaScript engine, the sum will be exactly 1.0. But this isn’t a guarantee for all fraction combinations. For example, 0.1 + 0.2 doesn’t equal 0.3 because their individual approximations don’t sum to an exact value. Your example just happens to hit a sweet spot where the rounding errors cancel out perfectly.
内容的提问来源于stack exchange,提问作者Josh Formal

