java中浮点到int转换的异常现象

llmtgqce  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(272)

正如标题所述,我正在尝试将一些浮点值转换为整数,我看到了一些异常值。例如,我有一个方法试图转换浮点的小数部分 .45 from 123.45 ,以字符串表示形式输出 45/100 .
问题是,对于 0.35, 0.45, 0.65 and 0.95 我明白了 0.34, 0.44, 0.64 and 0.94 分别。以下是我的实现:

public String convertDecimalPartToString(float input){

    int numberOfDigits = numberOfDigits(input);

    System.out.println(numberOfDigits);

    String numerator = Integer.toString((int) (input * Math.pow(10, numberOfDigits)));

    String denominator = Integer.toString((int) Math.pow(10, numberOfDigits));

    return numerator + "/" + denominator;
}

public int numberOfDigits(float input){

    String inputAsString = Float.toString(input);

    System.out.println(inputAsString);

    int digits = 0;
    // go to less than 2 because first 2 will be 0 and .
    for(int i =0;i<inputAsString.length()-2;i++){
        digits++;
    }
    return digits;
}

我的测试方法如下:

@Test
public void testConvertDecimalPartToString(){
    float input = 0.95f;
    //output is 94/100 and assert fails
    Assert.assertEquals("95/100", checkWriter.convertDecimalPartToString(input));

}

这行好像有个误判: String numerator = Integer.toString((int) (input * Math.pow(10, numberOfDigits))); 但我不明白为什么它对我的工作正常 0.05, 0.15, 0.25, 0.55, 0.75 and 0.85 .
有人能帮我理解吗?

kuhbmx9i

kuhbmx9i1#

问题是数字。假设我给了你3位(0或1个值):你只能用这个来表示8个不同的值:000,001,010,011,100,101,110和111。就这些。如果这是唯一的法律价值观,就不能代表8个以上的概念! float 是32位值。用32位,我可以给你40亿个不同的值。这是很多值,但它不是无限的,而且在0和1之间有无穷多的数字,更不用说在0和1之间了 340,282,346,638,528,860,000,000,000,000,000,000,000.000000 哪个是a的最大值 float 可以代表。
那这是怎么回事?不是每个数字都是可以表示的。目前只有大约40亿个数字。这些是受祝福的数字。
任何时候你试图做一个不受祝福的数字,或者一个计算的结果不受祝福,那么你的数字被四舍五入到最接近的祝福数字,如果你执行一系列的操作,这个四舍五入发生在每一步。
受祝福的数字的性质是,在0和1之间的受祝福数字和在1之上的受祝福数字一样多——当你离开0时,任何2个受祝福数字之间的间隔就会上升。事实上,最终它将超过1.0。
此外,计算机以二进制而不是十进制计数。就像你不能用十进制(0.33333。。。它永远不会结束),像0.1(1除以10)这样简单的东西不能用二进制完美地表示,所以像 1.0/10.0 已经轮到我了!
如果发生任何舍入,您的代码将失败。你的问题的解决方法相当简单;加上0.005就可以了。更好的方法是首先将其渲染为圆形字符串:

String x = String.format("%.02f", yourValue);

然后在绳子里找到你需要的东西。上面提到的是适当的四舍五入,它比使用math.pow做得更好,因为它会使你远离0,导致更多的错误出现(离0越远->更多的极端四舍五入错误,因为有更少的幸运数字)。
注:注意 double 它的速度和float一样快,而且假设你有64位可以在那里使用,它有更多的幸运数字,因此,错误更少。
nb2:另一种方法是将你的“单位”概念转移。例如,如果这代表现金,只需 int cents; -没有问题,知道祝福数字的意义就容易多了 int (介于-2^31和+2^31之间的每个整数)。

相关问题