我在测试一些HTML表单时遇到了这个问题。JavaScript 中带小数点的数字的最大位数仅为 16
我尝试了以下方法
var x = 12345678912345.6789
x 是 12345678912345.68 -仅限 16 位数字
var x = 123456789123.6789
x 是 123456789123.6789 -仅限 16 位数字
new Number(12345678912345.6789)
12345678912345.68 -仅 16 位数字
new Number(123456789123.6789)
123456789123.6789 -仅 16 位数字
如果计算总位数,它们是 16。如果增加小数点前的数字,则小数点后的数字将四舍五入
同样地
new Number(.12345678912367890)
是 0.1234567891236789 -仅 16 位数字(缺少尾随 0 的通知)
这让我推断出我只能在一个带有十进制的数字中有 16 位数字。如果我尝试添加更多数字,数字开始四舍五入
我还观察到,当我在 MVC 中将带有十进制的数字序列化为 JSoN 时 ASP.NET 它还会将该数字转换为最多 16 位数字并将其余数字四舍五入
我的问题:为什么?
根据 JS/ECMAScript 规范,Number
类型使用双精度浮点,该浮点具有 64 位格式 (binary64
),由一个符号位(确定正值或负值)、11 个指数位和 52 个分数位(每个数字代表 4 位,因此 64 位有 16 位
表示双精度 64 位格式 IEEE 的数字类型 IEEE 二进制标准中规定的 754-2008 值浮点运算。
使用双精度可以正确表示的最大正数是9007199254740992
,这可以通过使用Math.pow(2, 53)
来实现。如果数范围介于Math.pow(2, 53)
和Math.pow(2, 54)
之间(或介于Math.pow(2, -53)
和Math.pow(2, -54)
之间),则只能正确表示偶数,因为指数位将影响分数位上的 LSB(最低有效位)。
让我们回顾一下大数字部分:
var x = 12345678912345.6789
var x = new Number(12345678912345.6789)
此数字包含超过 52 个小数位(总共 72 位),因此用于将小数位保持在 52 的舍入。
同样具有以下十进制数:
var x = new Number(.12345678912367890)
这个数字包含 68 个小数位,因此最后一个零被砍掉以保持 64 位长度。
通常大于9007199254740992
或小于1.1102230246251565E-16
的数字表示形式存储为文本字符串而不是Number
。如果需要计算非常大的数字,则可以使用某些外部库来执行任意精度的算术。
延伸阅读:
ECMAScript:数字编码
ECMAScript:处理大整数
在 javascript 中,你不能用二进制浮点类型精确地表示大多数小数部分(这是 ECMAScript 用来表示浮点值的)。
这就是为什么javascript在小数点后使用16个数字。 例如-
尝试运行:
var x = 3.14159265358979323846;
print(x.toFixed(20));
并看到以下内容正在浮动。
如果要在小数点后投射超过 16 位,您可以:
- 使用文字字符串表示您的数字
- 使用外部库,如 math.js 或 BigInteger.js。