Number.toFixed函数中的四舍五入是如何工作的?

huangapple go评论83阅读模式
英文:

How does rounding work in Number.toFixed function?

问题

以下是翻译好的内容:

我正在用Java编写一个API,代码应该像另一个用Node编写的微服务一样运行。

在Node中存在问题的部分是这样的:

const totalValue =   // 这个值来自一个查询
const risk =         // 这是另一个查询中的百分比值

const riskValue = totalValue * (risk / 100);
const available = +(totalValue - riskValue).toFixed(2);

return available;

经过一些测试后,我用Java编写了以下API:

BigDecimal totalValue = ...
BigDecimal risk = ...

BigDecimal riskValue = totalValue.multiply(risk.divide(new BigDecimal(100)));
BigDecimal available = totalValue.subtract(riskValue).setScale(2, RoundingMode.HALF_DOWN));

几天后出现了第一个bug:

totalValue = 62822.65
risk = 10

Node返回:

56540.385.toFixed(2); // "56540.39"

这个特定的数字并没有按我在Java API中期望的方式进行半下舍入。

然而,这个数字是按半下舍入方式进行舍入的:

56540.395.toFixed(2); // "56540.39"

JavaScript中Number.toFixed(2)背后的逻辑是什么?

如何在Java中复制这个函数的行为?

提前致谢。

英文:

I am coding an API in Java, and the code should behave like another microservice written in Node.

The problematic part written in Node is this:

const totalValue =   // this value comes from a query
const risk =         // it is a percentage value from another query

const riskValue = totalValue * (risk / 100);
const available = +(totalValue - riskValue).toFixed(2);

return available;

After a few tests I coded the Java API this way:

BigDecimal totalValue = ...
BigDecimal risk = ...

BigDecimal riskValue = totalValue.multiply(risk.divide(new BigDecimal(100)));
BigDecimal available = totalValue.subtract(riskValue).setScale(2, RoundingMode.HALF_DOWN));

Some days later first bug:

totalValue = 62822.65
risk = 10

Node returns:

56540.385.toFixed(2); // "56540.39"

This specific number is not rounding half down as I expected it to happen in my Java API.

However, this number is rounding half down:

56540.395.toFixed(2); // "56540.39"

What's the logic behind JavaScript Number.toFixed(2)?

How to copy this function behavior in Java?

Thanks in advance.

答案1

得分: 1

以下是翻译好的代码部分:

我不确定我完全理解了你的问题如果你的问题是如何将一个 `double` 数字四舍五入到 `2` 位小数你可以按照以下方式操作

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
    public static void main(String[] args) {
        double n1 = 56540.385;
        BigDecimal rounded1 = BigDecimal.valueOf(n1).setScale(2, RoundingMode.HALF_UP);
        System.out.println(rounded1);

        double n2 = 56540.395;
        BigDecimal rounded2 = BigDecimal.valueOf(n2).setScale(2, RoundingMode.HALF_UP);
        System.out.println(rounded2);
    }
}

输出

56540.39
56540.40

如果你需要关于其他事情的帮助,请随时评论。

英文:

I'm not sure if I understood your question completely. If your question is how to round a double number up to 2 decimal places, you can do it as follows:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
	public static void main(String[] args) {
		double n1 = 56540.385;
		BigDecimal rounded1 = BigDecimal.valueOf(n1).setScale(2, RoundingMode.HALF_UP);
		System.out.println(rounded1);

		double n2 = 56540.395;
		BigDecimal rounded2 = BigDecimal.valueOf(n2).setScale(2, RoundingMode.HALF_UP);
		System.out.println(rounded2);
	}
}

Output

56540.39
56540.40

Feel free to comment in case you are seeking help regarding something else.

答案2

得分: 1

参考阿文德·库马尔·阿维纳什的回答

问题是,确切的数字 56540.38556540.395 不存在:浮点数始终是基于二进制而不是十进制的。

证明:

56540.385.toPrecision(18); // 返回 "56540.3850000000020"
56540.395.toPrecision(18); // 返回 "56540.3949999999968"

因此表达式 NUMBER.toFixed(2); 经过两个步骤处理:

  1. 数字 NUMBER 被扫描并转换为最近可能的浮点数。
  2. 对转换后的数字执行 toFixed()

而且,如果了解背后的数学原理,对于两种情况,6540.39 的结果都是正确的。

一个可能的解决方案是将所有计算都以分为单位计算(乘以100),然后对格式化输出使用 (NUMBER/100).toFixed(2)

英文:

Referencing the answer by Arvind Kumar Avinash

The problem is, that the exact numbers 56540.385 and 56540.395does not exist: Floats are always binary based and not decimal based.

Proof:

56540.385.toPrecision(18); // returns "56540.3850000000020"
56540.395.toPrecision(18); // returns "56540.3949999999968"

So the expression NUMBER.toFixed(2); is processed into 2 steps:

  1. NUMBER is scanned in transformed to the nearest possible floating point number.
  2. toFixed() is executed for the transformed number.

And if knowing this mathematics behind the scenes, the result of 6540.39 is correct for both cases.

A possible solution can be to calculate all in cent (factor 100) and then using (NUMBER/100).toFixed(2) for the formatted output.

huangapple
  • 本文由 发表于 2020年4月10日 05:25:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/61130477.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定