我打赌这里有一个类似的问题,所以,我就是找不到。问题是当我得到一个像235.00000002或9875.999999997这样的数字时,修复java数学的不精确性。当然,对于一个人来说,这两个词实际上意味着235和9876,当给定一定的精度阈值时,我们将其称为"5零或9“。
但这不仅仅是小数点右边的数字,同样的规则也应该适用于像23500000001.0和5699999999.0这样的数字
有什么想法/图书馆吗?
更新:似乎错了,我说这是一个已知的话题,几分钟后就会有一个已知的库出现。这就是我所期望的逻辑:对于一个给定的数字,当它的字符串表示中遇到N个连续的0或9时,这些0和9将与最右边的"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);答案肯定不是你会在购物车上看到的那个。在我的例子中,情况更糟,这不仅仅是我要处理的钱,它可以是任何东西--百分比,大数,小分数,所有这些都是相对繁重的数学计算的结果。所以我说的是对人类来说有意义的四舍五入。
我已经完成了代码,但仍然有可能有人做得更好。
发布于 2014-04-26 17:19:06
正如我在评论中所建议的那样,我使用了一些科学符号。以下是我想出的:
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编辑I调整代码使用双倍,修正了指数<0的错误,并添加了另一个示例。此外,我插入了一个DecimalFormat。请注意,添加更多的#可能会改变一些结果,即-0.053999949现在将显示为-0.054,它将产生更多的数字,从而导致-0.05399995。
发布于 2014-04-26 16:25:57
你可能在问如何存储和处理货币。简短的回答是:使用BigDecimal类型,或者使用单独的整数字段为欧元和美分创建自己的货币实现(或者美元,如果你喜欢:)。
发布于 2014-04-26 17:10:52
既然你问你的想法,这个怎么样:使N不是一个连续的0或9的数目,而是一个阈值,在这个阈值上,一个数字的四舍五入仍然接近于原来的数字。然后从最不重要的小数位开始,一次把第一位舍入,然后除以你以前得到的数字。如果比率超过阈值,请停止。试着用舍入对你有利的比率和边界条件。使用BigDecimal避免浮点算法的问题。
https://stackoverflow.com/questions/23313411
复制相似问题