我打赌在这里有一个类似的问题,我找不到它。
问题是关于修复java数学不准确性,例如我得到235.00000002
或9875.999999997
这样的数字。当然,对于一个人而言,这两个人实际上意味着235
和9876
,当给出一定的准确度阈值时,让我们称之为" 5个零或九个"
但不仅是小数点右边的数字,同样的规则也适用于23500000001.0
和5699999999.0
等数字
任何想法/图书馆?
更新
看起来我错了,说这是一个已知的主题,只需要几分钟,直到有人弹出一个已知的库。所以这是我期望的逻辑:
对于给定的数字,当在其字符串表示中遇到N个连续的零或九时,则这些零和九与最右边的数字的其余部分一起舍入" 0"或" 9"。
例如,当N = 5时,数字239999995.546
变为240000000.0
,数字34.0000007
变为34
,340000.007
变为340000
更新2:
这就是在匆忙或对问题不够重视时会发生什么。抱歉。我正在谈论"人类"四舍五入。一个很好的例子是在linux框中比较df
和df -h
的输出。至于"不准确"我在谈论,请运行以下代码:
double d = 1000.0;
double mult = 0.12351665;
System.out.println(d * mult / mult);
回复肯定不是您在购物车中显示的回复。在我的情况下,情况更糟,它不仅是我处理的钱,它可以是任何东西 - 百分比,大数,小分数,以及所有这些都是相对繁重的数学计算的结果。所以我在谈论对人类有意义的舍入。
我已经完成了代码,但仍有可能有人做得更好。
答案 0 :(得分:2)
您可能正在尝试询问如何存储和处理货币。简短的回答是:使用BigDecimal类型或使用单独的整数字段为欧元和美分创建您自己的货币实现(如果您愿意,则为美元:)。
答案 1 :(得分:2)
我在评论中已经提到了科学记数法。以下是我提出的建议:
public static double simplify(Number n) {
String numberString = String.format("%e", n);
int indexE = numberString.indexOf('e');
String baseValue = numberString.substring(0, indexE);
String exponent = numberString.substring(indexE + 1);
double base = Double.parseDouble(baseValue);
int exp = Integer.parseInt(exponent);
return base * Math.pow(10, exp);
}
我使用了我在你的问题中找到的所有数字,并添加了一个负值来测试它。
public static void main(String[] args) {
Number[] ns = new Number[]{
239999995.546,
239989995.546,
340000.007,
34.0000007,
5699999999.0,
235.00000002,
9875.999999997,
-4334.345345,
23500000001.0,
0.30000007,
-0.053999949
};
DecimalFormat df = new DecimalFormat("0.#####");
for(Number n : ns) {
String s = df.format(simplify(n));
System.out.println(" " + n + " is " + s);
}
}
结果是:
2.39999995546E8 is 240000000
2.39989995546E8 is 239990000
340000.007 is 340000
34.0000007 is 34
5.699999999E9 is 5700000000
235.00000002 is 235
9875.999999997 is 9876
-4334.345345 is -4334.345
2.3500000001E10 is 23500000000
0.30000007 is 0.3
-0.053999949 is -0.054
编辑我调整了代码以使用double,用exponents<修正了错误0并添加了另一个例子。另外我插入了DecimalFormat
。请注意,添加更多#
可能会更改某些结果,即-0.053999949
现在会显示为-0.054
,更多数字会导致-0.05399995
。
答案 2 :(得分:1)
既然你提出了想法,那么这个怎么样:使N不是一个连续的零或九的数量,而是一个数字四舍五入仍然接近原始数字的阈值。然后从最不重要的小数位开始,一次将第一个位置四舍五入,然后将你得到的数字除以之前的数字。如果比率超过您的阈值则停止。试验圆角看起来对你好的比例和边界条件。使用BigDecimal可以避免浮点运算的问题。