首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java数字,“人”四舍五入

Java数字,“人”四舍五入
EN

Stack Overflow用户
提问于 2014-04-26 16:09:37
回答 3查看 214关注 0票数 0

我打赌这里有一个类似的问题,所以,我就是找不到。问题是当我得到一个像235.000000029875.999999997这样的数字时,修复java数学的不精确性。当然,对于一个人来说,这两个词实际上意味着2359876,当给定一定的精度阈值时,我们将其称为"5零或9“。

但这不仅仅是小数点右边的数字,同样的规则也应该适用于像23500000001.05699999999.0这样的数字

有什么想法/图书馆吗?

更新:似乎错了,我说这是一个已知的话题,几分钟后就会有一个已知的库出现。这就是我所期望的逻辑:对于一个给定的数字,当它的字符串表示中遇到N个连续的0或9时,这些0和9将与最右边的"0“或"9”右边的数的其余部分一起舍入。例如,当N=5时,数字239999995.546变成240000000.0,数字34.0000007变成34,而340000.007变成340000

更新2:,这是在匆忙或对问题没有足够注意的时候发生的。抱歉的。我说的是“人”的四舍五入。一个很好的例子是比较linux上dfdf -h的输出。至于我所说的“不准确”,请运行以下代码:

代码语言:javascript
复制
double d = 1000.0;
double mult = 0.12351665;
System.out.println(d * mult / mult);

答案肯定不是你会在购物车上看到的那个。在我的例子中,情况更糟,这不仅仅是我要处理的钱,它可以是任何东西--百分比,大数,小分数,所有这些都是相对繁重的数学计算的结果。所以我说的是对人类来说有意义的四舍五入。

我已经完成了代码,但仍然有可能有人做得更好。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-26 17:19:06

正如我在评论中所建议的那样,我使用了一些科学符号。以下是我想出的:

代码语言:javascript
复制
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);
}

我使用了我在你的问题中发现的所有数字,并且增加了一个负值来测试它。

代码语言:javascript
复制
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);
    }
}

研究结果如下:

代码语言:javascript
复制
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

票数 2
EN

Stack Overflow用户

发布于 2014-04-26 16:25:57

你可能在问如何存储和处理货币。简短的回答是:使用BigDecimal类型,或者使用单独的整数字段为欧元和美分创建自己的货币实现(或者美元,如果你喜欢:)。

已经解释过:Using BigDecimal to work with currencies

Why not use Double or Float to represent currency?

票数 2
EN

Stack Overflow用户

发布于 2014-04-26 17:10:52

既然你问你的想法,这个怎么样:使N不是一个连续的0或9的数目,而是一个阈值,在这个阈值上,一个数字的四舍五入仍然接近于原来的数字。然后从最不重要的小数位开始,一次把第一位舍入,然后除以你以前得到的数字。如果比率超过阈值,请停止。试着用舍入对你有利的比率和边界条件。使用BigDecimal避免浮点算法的问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23313411

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档