在 JavaScript 中格式化精确到两位小数的数字
我有这行代码,将我的数字四舍五入到小数点后两位。但我得到这样的数字:10.8、2.4 等。这些不是我对两位小数的想法,所以我如何改进以下内容?
Math.round(price*Math.pow(10,2))/Math.pow(10,2);
我想要 10.80、2.40 等数字。使用 jQuery 对我来说没问题。
I have this line of code which rounds my numbers to two decimal places. But I get numbers like this: 10.8, 2.4, etc. These are not my idea of two decimal places so how I can improve the following?
Math.round(price*Math.pow(10,2))/Math.pow(10,2);
I want numbers like 10.80, 2.40, etc. Use of jQuery is fine with me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
要使用定点表示法格式化数字,您只需使用 toFixed< /a> 方法:
请注意,
toFixed()
返回一个字符串。重要:请注意,toFixed 不会在 90% 的情况下进行舍入,它会返回舍入后的值,但在很多情况下,它不起作用。
例如:
2.005.toFixed(2) === "2.00"
更新:
现在,您可以使用
Intl.NumberFormat
构造函数。它是 ECMAScript 国际化 API 规范 (ECMA402) 的一部分。它具有相当好的浏览器支持,甚至包括 IE11,而且Node.js 完全支持。您也可以使用
toLocaleString
方法,该方法在内部将使用Intl
API:此 API 还为您提供了多种格式选项,例如千位分隔符、货币符号等。
To format a number using fixed-point notation, you can simply use the toFixed method:
Note that
toFixed()
returns a string.IMPORTANT: Note that toFixed does not round 90% of the time, it will return the rounded value, but for many cases, it doesn't work.
For instance:
2.005.toFixed(2) === "2.00"
UPDATE:
Nowadays, you can use the
Intl.NumberFormat
constructor. It's part of the ECMAScript Internationalization API Specification (ECMA402). It has pretty good browser support, including even IE11, and it is fully supported in Node.js.You can alternatively use the
toLocaleString
method, which internally will use theIntl
API:This API also provides you a wide variety of options to format, like thousand separators, currency symbols, etc.
这是一个古老的话题,但仍然在 Google 结果中名列前茅,并且提供的解决方案也存在相同的浮点小数问题。这是我使用的(非常通用的)函数, 感谢 MDN:
正如我们所看到的,我们没有遇到这些问题:
这种通用性还提供了一些很酷的东西:
现在,要回答 OP 的问题,必须输入:
或者,对于更简洁、更少通用的函数:
您可以通过以下方式调用它:
各种示例和测试(感谢 @tj-crowder< /strong>!):
This is an old topic but still top-ranked Google results and the solutions offered share the same floating point decimals issue. Here is the (very generic) function I use, thanks to MDN:
As we can see, we don't get these issues:
This genericity also provides some cool stuff:
Now, to answer the OP's question, one has to type:
Or, for a more concise, less generic function:
You can call it with:
Various examples and tests (thanks to @t-j-crowder!):
我通常将其添加到我的个人库中,经过一些建议并使用 @TIMINeutron 解决方案,并使其适应十进制长度,然后,这个最适合:
将适用于报告的异常。
I usually add this to my personal library, and after some suggestions and using the @TIMINeutron solution too, and making it adaptable for decimal length then, this one fits best:
will work for the exceptions reported.
快速简单的
示例
FAST AND EASY
Example
100% 确保您得到小数点后 2 位的数字的一种方法:
如果这导致舍入错误,您可以使用以下内容,正如 James 在他的评论中所解释的那样:
One way to be 100% sure that you get a number with 2 decimals:
If this causes rounding errors, you can use the following as James has explained in his comment:
我不知道为什么我不能在以前的答案中添加评论(也许我是盲目的,我不知道),但我使用@Miguel的答案想出了一个解决方案:
及其两条评论(来自@bighostkim 和 @Imre):
precise_round(1.275,2)
不返回 1.28 的precise_round(6,2)
不返回 6.00 的问题(如他所愿)。我的最终解决方案如下:
如您所见,我必须添加一点“校正”(这不是它的本质,但由于 Math.round 是有损的 - 您可以在 jsfiddle.net 上检查它 - 这是唯一的我知道如何“修复”它)。它在已经填充的数字上添加了 0.001,因此它在十进制值的右侧添加了三个
0
的1
。所以使用起来应该是安全的。之后,我添加了
.toFixed(decimal)
以始终以正确的格式输出数字(具有正确的小数位数)。就这样了。好好利用它;)
编辑:添加负数“校正”功能。
I don't know why can't I add a comment to a previous answer (maybe I'm hopelessly blind, I don't know), but I came up with a solution using @Miguel's answer:
And its two comments (from @bighostkim and @Imre):
precise_round(1.275,2)
not returning 1.28precise_round(6,2)
not returning 6.00 (as he wanted).My final solution is as follows:
As you can see I had to add a little bit of "correction" (it's not what it is, but since Math.round is lossy - you can check it on jsfiddle.net - this is the only way I knew how to "fix" it). It adds 0.001 to the already padded number, so it is adding a
1
three0
s to the right of the decimal value. So it should be safe to use.After that I added
.toFixed(decimal)
to always output the number in the correct format (with the right amount of decimals).So that's pretty much it. Use it well ;)
EDIT: added functionality to the "correction" of negative numbers.
使用下面的方法
并且如果您希望该数字是固定的,请使用
Use this method below
AND if you want the number to be fixed use
这是一个简单的
用法,例如
alert(roundFloat(1.79209243929,4));
Jsfiddle
Here's a simple one
Use like
alert(roundFloat(1.79209243929,4));
Jsfiddle
我没有找到这个问题的准确解决方案,所以我创建了自己的:
示例:
I didn't find an accurate solution for this problem, so I created my own:
Examples:
向下舍入
向上舍入
舍入最接近的值
Round down
Round up
Round nearest
在 Christian C. Salvadó 的回答之上构建,执行以下操作将输出
Number
类型,并且似乎也能很好地处理舍入:上面的内容与已经提到的内容之间的区别在于,当您正在使用它[,并且它输出一个
Number
类型]。Building on top of Christian C. Salvadó's answer, doing the following will output a
Number
type, and also seems to be dealing with rounding well:The difference between the above and what has already been mentioned is that you don't need the
.format()
chaining when you're using it[, and that it outputs aNumber
type].@heridev 和我在 jQuery 中创建了一个小函数。
您可以尝试下一步:
HTML
jQuery
在线演示:
http://jsfiddle.net/c4Wqn/
@heridev and I created a small function in jQuery.
You can try next:
HTML
jQuery
DEMO ONLINE:
http://jsfiddle.net/c4Wqn/
浮点值的问题在于它们试图用固定数量的位来表示无限数量的(连续的)值。所以很自然地,在游戏中肯定会有一些损失,并且你会被一些价值观所困扰。
当计算机将 1.275 存储为浮点值时,它实际上不会记住它是 1.275 还是 1.27499999999999993,甚至是 1.27500000000000002。这些值在四舍五入到两位小数后应该会给出不同的结果,但它们不会,因为对于计算机来说,它们在存储为浮点值后看起来完全相同,并且无法恢复丢失的数据。任何进一步的计算只会累积这种不精确性。
因此,如果精度很重要,您必须从一开始就避免使用浮点值。最简单的选择是
例如,当使用整数存储百分之数时,查找实际值的函数非常简单:
对于字符串,您需要舍入,但它仍然是可以管理的:
请注意,此函数舍入到最接近的值,远离零,而IEEE 754 建议舍入到最接近的值,趋于偶数作为浮点运算的默认行为。这些修改留给读者作为练习:)
The trouble with floating point values is that they are trying to represent an infinite amount of (continuous) values with a fixed amount of bits. So naturally, there must be some loss in play, and you're going to be bitten with some values.
When a computer stores 1.275 as a floating point value, it won't actually remember whether it was 1.275 or 1.27499999999999993, or even 1.27500000000000002. These values should give different results after rounding to two decimals, but they won't, since for computer they look exactly the same after storing as floating point values, and there's no way to restore the lost data. Any further calculations will only accumulate such imprecision.
So, if precision matters, you have to avoid floating point values from the start. The simplest options are to
For example, when using integers to store the number of hundredths, the function for finding the actual value is quite simple:
With strings, you'll need rounding, but it's still manageable:
Note that this function rounds to nearest, ties away from zero, while IEEE 754 recommends rounding to nearest, ties to even as the default behavior for floating point operations. Such modifications are left as an exercise for the reader :)
四舍五入您的小数值,然后使用
toFixed(x)
作为您的预期数字。调用
parseDecimalRoundAndFixed(10.800243929,4) => 10.80
parseDecimalRoundAndFixed(10.807243929,2) => 10.81
Round your decimal value, then use
toFixed(x)
for your expected digit(s).Call
parseDecimalRoundAndFixed(10.800243929,4) => 10.80
parseDecimalRoundAndFixed(10.807243929,2) => 10.81
这对我有用: JavaScript 中的舍入小数
This worked for me: Rounding Decimals in JavaScript
通过这些示例,当尝试对数字 1.005 进行四舍五入时,您仍然会收到错误,解决方案是使用 Math.js 等库或此函数:
With these examples you will still get an error when trying to round the number 1.005 the solution is to either use a library like Math.js or this function:
这是我的 1 行解决方案:
Number((yourNumericValueHere).toFixed(2));
发生的情况如下:
1) 首先,应用
.toFixed( 2)
到您想要四舍五入小数位的数字上。请注意,这会将值从数字转换为字符串。因此,如果您使用 Typescript,它会抛出如下错误:“Type 'string' is not assignable to type 'number'”
2) 要返回数值或将字符串转换为数值,只需应用 < code>Number() 函数作用于所谓的“字符串”值。
为了便于说明,请查看下面的示例:
示例:
我的金额最多有 5 位小数,我想将其缩短到最多 2 位小数。我这样做是这样的:
Here is my 1-line solution:
Number((yourNumericValueHere).toFixed(2));
Here's what happens:
1) First, you apply
.toFixed(2)
onto the number that you want to round off the decimal places of. Note that this will convert the value to a string from number. So if you are using Typescript, it will throw an error like this:"Type 'string' is not assignable to type 'number'"
2) To get back the numeric value or to convert the string to numeric value, simply apply the
Number()
function on that so-called 'string' value.For clarification, look at the example below:
EXAMPLE:
I have an amount that has upto 5 digits in the decimal places and I would like to shorten it to upto 2 decimal places. I do it like so:
一般来说,小数舍入是通过缩放完成的:
round(num * p) / p
简单实现
使用以下具有中间数字的函数,您将获得上舍入值正如预期的那样,或者有时取决于输入的较低舍入值。
舍入中的这种
不一致
可能会在客户端代码中引入难以检测的错误。更好的实现
通过将数字转换为指数表示法中的字符串,正数将按预期四舍五入。
但是,请注意负数的舍入方式与正数的舍入方式不同。
事实上,它执行的规则基本上相当于 “round half up” 规则,您将看到
round(-1.005, 2)
的计算结果为-1
,即使round(1.005, 2)
的计算结果为1.01 。 lodash _.round 方法使用此技术。
如果您希望在舍入负数时采用通常的行为,则需要在调用 Math.round(),然后在返回之前将它们转换回负数。
有一种不同的纯数学技术来执行舍入到最接近的值(使用 "从零舍入一半"),其中在调用舍入函数之前应用epsilon 校正。
简而言之,我们在四舍五入之前将尽可能小的浮点值(= 1.0 ulp;单位在最后一位)添加到数字上。这将移动到数字之后的下一个可表示的值,远离零。
这是为了抵消编码期间可能发生的隐式舍入误差小数位数,特别是小数点最后一位为“5”的数字,例如 1.005、2.675 和 16.235。实际上,十进制的
1.005
被编码为64位二进制浮点数的1.0049999999999999
;而十进制的1234567.005
会被编码为64位二进制浮点数的1234567.0049999998882413
。值得注意的是,最大二进制
舍入误差
取决于 (1) 数字的大小和 (2) 相对机器 epsilon (2^-52)。In general, decimal rounding is done by scaling:
round(num * p) / p
Naive implementation
Using the following function with halfway numbers, you will get either the upper rounded value as expected, or the lower rounded value sometimes depending on the input.
This
inconsistency
in rounding may introduce hard to detect bugs in the client code.Better implementations
By converting the number to a string in the exponential notation, positive numbers are rounded as expected.
But, be aware that negative numbers round differently than positive numbers.
In fact, it performs what is basically equivalent to "round half up" as the rule, you will see that
round(-1.005, 2)
evaluates to-1
even thoughround(1.005, 2)
evaluates to1.01
. The lodash _.round method uses this technique.If you want the usual behavior when rounding negative numbers, you would need to convert negative numbers to positive before calling Math.round(), and then convert them back to negative numbers before returning.
There is a different purely mathematical technique to perform round-to-nearest (using "round half away from zero"), in which epsilon correction is applied before calling the rounding function.
Simply, we add the smallest possible float value (= 1.0 ulp; unit in the last place) to the number before rounding. This moves to the next representable value after the number, away from zero.
This is needed to offset the implicit round-off error that may occur during encoding of decimal numbers, particularly those having "5" in the last decimal position, like 1.005, 2.675 and 16.235. Actually,
1.005
in decimal system is encoded to1.0049999999999999
in 64-bit binary float; while,1234567.005
in decimal system is encoded to1234567.0049999998882413
in 64-bit binary float.It is worth noting that the maximum binary
round-off error
is dependent upon (1) the magnitude of the number and (2) the relative machine epsilon (2^-52).将以下放在某个全局范围内:
然后然后尝试:
更新
请注意,
toFixed()
只能适用于之间的小数位数>0-20
即a.getDecimals(25)
可能会生成 JavaScript 错误,因此为了适应,您可以添加一些额外的检查 iePut the following in some global scope:
and then try:
Update
Note that
toFixed()
can only work for the number of decimals between0-20
i.e.a.getDecimals(25)
may generate a javascript error, so to accomodate that you may add some additional check i.e.这将返回一个从 1 到 100 的随机数,四舍五入到小数点后两位。
this will return a random number from 1 to 100 rounded to 2 decimal places.
通过引用使用此响应: https://stackoverflow.com/a/21029698/454827
我构建了一个函数来获取动态小数位数:
这里工作示例: https://jsfiddle.net/wpxLduLc/
Using this response by reference: https://stackoverflow.com/a/21029698/454827
I build a function to get dynamic numbers of decimals:
here working example: https://jsfiddle.net/wpxLduLc/
几个月前,我从这篇文章中得到了一些想法,但这里的答案和其他帖子/博客的答案都不能处理所有场景(例如负数和我们的测试人员发现的一些“幸运数字”)。最终我们的测试人员并没有发现下面这个方法有什么问题。粘贴我的代码片段:
我还有代码注释(抱歉我已经忘记了所有详细信息)...我在这里发布我的答案以供将来参考:
I got some ideas from this post a few months back, but none of the answers here, nor answers from other posts/blogs could handle all the scenarios (e.g. negative numbers and some "lucky numbers" our tester found). In the end, our tester did not find any problem with this method below. Pasting a snippet of my code:
I also have code comments (sorry i forgot all the details already)...I'm posting my answer here for future reference:
我正在修复修改器的问题。
仅支持 2 位小数。
I'm fix the problem the modifier.
Support 2 decimal only.
那应该产生:
10.20
那应该产生:
0.05
那应该产生:
4.04
等等。
That should yield:
10.20
That should yield:
0.05
That should yield:
4.04
etc.
这非常简单,并且与其他任何方法一样有效:
由于 toFixed() 只能对数字调用,并且不幸的是返回一个字符串,因此这会为您完成两个方向的所有解析。您可以传递一个字符串或一个数字,每次都会返回一个数字!调用 parseNumber(1.49) 将为您提供 1,而调用 parseNumber(1.49,2) 将为您提供 1.50。就像他们中最好的一样!
This is very simple and works just as well as any of the others:
Since toFixed() can only be called on numbers, and unfortunately returns a string, this does all the parsing for you in both directions. You can pass a string or a number, and you get a number back every time! Calling parseNumber(1.49) will give you 1, and parseNumber(1.49,2) will give you 1.50. Just like the best of 'em!
您还可以使用
.toPrecision()
方法和一些自定义代码,并且无论 int 部分的长度如何,始终四舍五入到第 n 个十进制数字。您也可以将其制作为插件以更好地使用。
You could also use the
.toPrecision()
method and some custom code, and always round up to the nth decimal digit regardless the length of int part.You could also make it a plugin for a better use.
下面是 https://stackoverflow.com/a/21323330/916734 的 TypeScript 实现。它还通过函数使事情变得干燥,并允许可选的数字偏移。
Here's a TypeScript implementation of https://stackoverflow.com/a/21323330/916734. It also dries things up with functions, and allows for a optional digit offset.