Math.round的两个不同输出(double * Math.pow(10,int))

时间:2017-08-19 07:35:05

标签: java android

我遇到了一个非常奇怪的问题。我从同一个操作得到两个不同的输出。问题在这里描述。

double num = 2.0170818E7; 
int dp = 4;

String s = (Math.round(num * Math.pow(10, dp)) / (int) Math.pow(10, dp)) + "";

当我在Android 5.0+中运行上面的代码集时,我得到的输出为:

正确输出:

20170818

当我在Android 5.0下面运行上面的代码集时(我尝试使用4.4.2版本),我得到输出为:

输出错误:

20172835

正确的输出是20170818或预期的输出。为什么我会遇到这个奇怪的问题?

4 个答案:

答案 0 :(得分:7)

最初Android开发工具仅支持jdk 6功能。但是在2013年10月首先由Android Studio 0.3.2更改了。如果您的目标是Android 5.0及更高版本,则需要.Java 7或更高版本。现在可以使用java 8的一些功能。

JDK 8对问题JDK-7131459: DecimalFormat produces wrong format() results when close to a tie中的DecimalFormat四舍五入进行了故意更改。

但是,这些更改引入了一个真正的错误,其归档为JDK-8039915: Wrong NumberFormat.format() HALF_UP rounding when last digit exactly at rounding position greater than 5。例如:

99.9989 -> 100.00
99.9990 ->  99.99

Oracle修复了Java 8 update 40

中的这个错误

答案 1 :(得分:2)

BigDecimal实现:

    double num = 2.0170818E7; 
    int dp = 4;
    BigDecimal pow = new BigDecimal(Math.pow(10, dp));
    BigDecimal bigDecimal = new BigDecimal(num);
    BigDecimal result = bigDecimal.multiply(pow);
    result = result.divide(pow);
    String s = result.toString();

答案 2 :(得分:0)

[我没有准备好Android环境,因此无法自行检查...]

检查Math.pow(10,dp)的值。它可能是不精确的(可能是9999.999999左右,查看结果数字。将其转换为int给出9999而不是10000。

将其替换为足够大小的static final int[] POWERS = {1, 10, 100, 1000, 10000 ... }数组,并使用POWERS[dp]代替Math.pow(10,dp)计算。那你就有了确切的价值。

或者至少直接除以Math.pow()表达式,而不是它的int-cast,截断值。

答案 3 :(得分:0)

你得到这种“奇怪”的行为,因为你在Java中做浮点算术。除非你用完整数范围,否则只有整数的算术是准确的。另一方面,浮点运算并不精确,因为一些实数需要表示无限数量的数字。在Java中,当您开始使用“double”或“float”进行实际计算时(其值超出int范围),您的程序将变得不确定。从您的一条评论中我了解到您是一名物理学家,因此您可能对确定性计算感兴趣,如果是这样,您可能需要考虑使用strictfp库(Java有一个strictfp选项,我不知道Android)