固定()和精度()之间的区别?

我刚接触 JavaScript,刚刚发现 toFixed()toPrecision()是整数。然而,我想不出这两者之间有什么区别。

number.toFixed()number.toPrecision()有什么不同?

68989 次浏览

我相信前者给你一个固定的小数位数,而后者给你一个固定的有效数字位数。

Math.PI.toFixed(2); // "3.14"
Math.PI.toPrecision(2); // "3.1"

此外,如果数字中的整数数字多于指定的精度,则 toPrecision将生成 科学记数法

(Math.PI * 10).toPrecision(2); // "31"
(Math.PI * 100).toPrecision(2); // "3.1e+2"

编辑: 对了,如果你刚接触 JavaScript,我可以向你强烈推荐道格拉斯·克罗克福特的书《 JavaScript: 好的部分》。

toFixed(n)提供小数点后的 n长度; toPrecision(x)提供 x总长度。

在 w3学校的裁判: 修好了精确

编辑:
不久前我得知 W3school 并不是最好的信息来源,但是我忘记了这个答案,直到我看到 Kzh 的,呃,“热情”的评论。以下是来自 Mozilla Doc Center toFixed()对于 toPrecision()的其他参考文献。对我们所有人来说幸运的是,在这种情况下,MDC 和 w3school 是一致的。

为了完整起见,我应该提到,toFixed()等同于 toFixed(0),而 toPrecision()只返回原始数字,没有格式化。

在某些情况下,toPrecision()将返回指数符号,而 toFixed()不会。

我认为最好用一个例子来回答这个问题。

假设你有以下数据:

var products = [
{
"title": "Really Nice Pen",
"price": 150
},
{
"title": "Golf Shirt",
"price": 49.99
},
{
"title": "My Car",
"price": 1234.56
}
]

您需要显示这些产品的标题和格式化的价格。让我们先尝试使用 toPrecision:

document.write("The price of " + products[0].title + " is $" + products[0].price.toPrecision(5));


The price of Really Nice Pen is $150.00

看起来不错,所以你可能会认为这也适用于其他产品:

document.write("The price of " + products[1].title + " is $" + products[2].price.toPrecision(5));
document.write("The price of " + products[2].title + " is $" + products[2].price.toPrecision(5));


The price of Golf Shirt is $49.990
The price of My Car is $1234.6

不太好。我们可以通过改变每个产品的有效数字数量来解决这个问题,但是如果我们在产品数组上迭代,那就有点棘手了。让我们改用 toFixed:

document.write("The price of " + products[0].title + " is $" + products[0].price.toFixed(2));
document.write("The price of " + products[1].title + " is $" + products[2].price.toFixed(2));
document.write("The price of " + products[2].title + " is $" + products[2].price.toFixed(2));


The price of Really Nice Pen is $150.00
The price of Golf Shirt is $49.99
The price of My Car is $1234.56

这将产生您所期望的结果,不涉及猜测工作,也不需要舍入。

只要:

49.99.toFixed(5)
// → "49.99000"


49.99.toPrecision(5)
// → "49.990"

例如,我们将变量 a 视为, Var a = 123.45 A.toPrecision (6) 输出是123.450 A.tofix (6) 输出类似于小数点后的123.450000//6位数字

例子说得很清楚:

var A = 123.456789;


A.toFixed()      // 123
A.toFixed(0)     // 123
A.toFixed(1)     // 123.5      round up last
A.toFixed(2)     // 123.46     round up last
A.toFixed(3)     // 123.457    round up last
A.toFixed(4)     // 123.4568   round up last
A.toFixed(5)     // 123.45679  round up last
A.toFixed(6)     // 123.456789
A.toFixed(7)     // 123.4567890
A.toFixed(8)     // 123.45678900
A.toFixed(9)     // 123.456789000
A.toFixed(10)    // 123.4567890000
A.toFixed(11)    // 123.45678900000


A.toPrecision()      // 123.456789
A.toPrecision(0)     // --- ERROR ---
A.toPrecision(1)     // 1e+2
A.toPrecision(2)     // 1.2e+2
A.toPrecision(3)     // 123
A.toPrecision(4)     // 123.5      round up last
A.toPrecision(5)     // 123.46     round up last
A.toPrecision(6)     // 123.457    round up last
A.toPrecision(7)     // 123.4568   round up last
A.toPrecision(8)     // 123.45679  round up last
A.toPrecision(9)     // 123.456789
A.toPrecision(10)    // 123.4567890
A.toPrecision(11)    // 123.45678900


// ----------------------
// edge-case rounding
// ----------------------
var B = 999.99;
B.toFixed(0)      // 1000
B.toFixed(1)      // 1000.0
B.toFixed(2)      // 999.99
B.toFixed(3)      // 999.990


B.toPrecision(0)  // --- ERROR ----
B.toPrecision(1)  // 1e+3
B.toPrecision(2)  // 1.0e+3
B.toPrecision(3)  // 1.00e+3
B.toPrecision(4)  // 1000
B.toPrecision(5)  // 999.99
B.toPrecision(6)  // 999.990


var C = 0.99;
C.toFixed(0)      // 1
C.toFixed(1)      // 1.0
C.toFixed(2)      // 0.99
C.toFixed(3)      // 0.990


C.toPrecision(0)  // --- ERROR ----
C.toPrecision(1)  // 1
C.toPrecision(2)  // 0.99
C.toPrecision(3)  // 0.990

toPrecision()toFixed()都是设计用来在打印前格式化数字的函数。因此它们都返回 String值。

但有一个例外。如果对 没有数字文字使用这些函数,由于运算符优先级,将返回一个数字。这意味着 toFixed()toPrecision()将首先返回一个字符串,然后 -减号运算符将字符串转换回一个数字作为负值。请看下面的例子。

返回一个表示数字对象的 String,以四舍五入到有效数字的定点或指数符号表示。因此,如果指定精度为1,它会返回第一个有效数字,以及表示10的幂的科学记数法,如果有效数字 < 0,则返回小数点前的0。

const num1 = 123.4567;


// if no arguments are passed, it is similar to converting the Number to String
num1.toPrecision();   // returns "123.4567


// scientific notation is used when you pass precision count less than total
// number of digits left of the period
num1.toPrecision(2);  // returns "1.2e+2"


// last digit is rounded if precision is less than total significant digits
num1.toPrecision(4);  // returns "123.5"
num1.toPrecision(5);  // returns "123.46"


const largeNum = 456.789;
largeNum.toPrecision(2);  // returns "4.6e+2"


// trailing zeroes are added if precision is > total digits of the number or float
num1.toPrecision(9);  // returns "123.456700"


const num2 = 123;
num2.toPrecision(4);  // returns "123.0"


const num3 = 0.00123;
num3.toPrecision(4);  // returns "0.001230"
num3.toPrecision(5);  // returns "0.0012300"


// if the number is < 1, precision is by the significant digits
num3.toPrecision(1);  // returns "0.001"

toFixed()以四舍五入的定点表示法返回一个表示 Number 对象的 String。这个函数只关心小数点数

const num1 = 123.4567;


// if no argument is passed, the fractions are removed
num1.toFixed();  // returns "123"


// specifying an argument means you the amount of numbers after the decimal point
num1.toFixed(1);  // returns "123.5"
num1.toFixed(3);  // returns "123.457"
num1.toFixed(5);  // returns "123.45670"
num1.toFixed(7);  // returns "123.4567000"


// trying to operator on number literals
2.34.toFixed(1);  // returns "2.3"
2.toFixed(1);     // returns SyntaxError
(2).toFixed(1);   // returns "2.0"
(2.34e+5).toFixed(1);  // returns "234000.0"


上面我提到过一个例外,在负数字字面值上使用这些函数,由于操作符优先级的原因,将返回一个数字而不是一个字符串。下面是一些例子:

// Note: these are returning as Number
// toPrecision()
-123.45.toPrecision();  // returns -123.45
-123.45.toPrecision(2);  // returns -120
-123.45.toPrecision(4);  // returns -123.5
-2.34e+2.toPrecision(1);  // returns -200
-0.0456.toPrecision(1);  // returns -0.05
-0.0456.toPrecision(6);  // returns -0.0456


// toFixed()
-123.45.toFixed();  // returns -123.45
-123.45.toFixed(1);  // returns -123.5
-123.45.toFixed(4);  // returns -123.45
-0.0456.toFixed(1);  // returns -0
-0.0456.toFixed(6);  // -0.0456

有趣的是,从 -0.0456.toFixed(1)中可以看到有符号的零

见: + 0和 -0是一样的吗?

toFixed(fractionDigits?)在其他答案中或多或少得到了准确的解释:

  • 它返回一个字符串表示,表示小数点后面的 fractionDigits[ amount ]位数:

举个例子:

(-3).toFixed(1)     // '-3.0'
(-3).toFixed(0)     // '-3'
(-3).toFixed()      // '-3'
(-0.03).toFixed(1)  // '-0.0'

toPrecision(precision?) 在以前的答案中没有被正确地描述,所以应该注意。 我还要补充一个免责声明,我还没有能够消化 toPrecision的规范,所以接下来的几点是基于在 Node.js 中测试实现的尝试和错误方法。这些步骤并不能覆盖所有的角落情况,比如如果数字是 NaN,或者精度参数不是整数,或者是 < 1或 > 100等等。这是为了不使解释杂乱无章,因为规范似乎是。

* 案例的编号通过列表保留,尽管案例可能看起来与其他案例相似,但它们需要证明一个特定的行为

  1. 它首先以指数记数法表示数字,其中 precision 表示有效数字中的数位数,如

案例1: 0.000004→精度 = 3→ 400 * 10^-8
案例2: 0.0000004→精度 = 3→ 400 * 10^-9
案例3: 123→精度 = 1→ 1.23 * 10^2
案例4: 153→精度 = 1→ 1.53 * 10^2
案例5: 1234.56→精度 = 3→ 123.456 * 10^1
案例6: 1234.56→精度 = 5→ 12345.6 * 10^-1

  1. 然后才是最重要的部分

病例1: 400 * 10^-8400 * 10^-8(无分数存在,无变化)
案例2: 400 * 10^-9400 * 10^-9(与案例1的推理相同)
病例3: 1.23 * 10^21 * 10^2(1.23四舍五入为 1)
病例4: 1.53 * 10^22 * 10^2(1.53四舍五入至 2)
案例5: 123.456 * 10^1123 * 10^1(也是四舍五入)
案例6: 12345.6 * 10^-112346 * 10^-1(四舍五入)

  1. 然后它生成一个字符串表示形式 ,表示遵循规则的数字:

3a) 步骤2中的有效数字的所有数字都会被保留

如果 precision < 该点前面的位数(在“正常”,即小数) ,则使用 指数表示法

案例3: 1 * 10^2'1e+2'(数字现在是 100,3位,精度是1,使用指数)
案例4: 2 * 10^2'2e+2'(数字现在是 200,3位,精度是1,使用指数)
案例5: 123 * 10^1'1.23e+3'(数字现在是 1230,4位,精度是3,使用指数; 注意,有意义符号保留了步骤2中的所有数字: 123变成 1.23)

3c) 如果数字的整数部分为0,并且在小数点后面和第一个有效数字(在“普通”符号中)前面的零的数目大于5,则使用指数符号

案例2: 400 * 10^-9'4.00e-7'(数字是0.0000004,它有 0整数部分,小数点后面有 > 5个零,请注意,来自 400 * 10^-9 被保存了下来)

3d) Decimal 符号,如果数字有0整数部分和小数点 < = 5之后的零数,但是步骤2的有效数字将被保留

病例1: 400 * 10^-8'0.00000400'(有效部分的两个零被保留)

precision > = 小数前面的位数,则使用 Decimal 记数法

案例6: 12346 * 10^-11234.6(步骤2中数字的十进制形式是1234.6,精度是5,小数点前的数字是4,字符串使用十进制表示法,步骤2中的所有有效数字都被保留)

console.log((0.000004).toPrecision(3));
console.log((0.0000004).toPrecision(3));
console.log((123).toPrecision(1));
console.log((153).toPrecision(1));
console.log((1234.56).toPrecision(3));
console.log((1234.56).toPrecision(5));