正如标题所述,我正在尝试将一些浮点值转换为整数,我看到了一些异常值。例如,我有一个方法试图转换浮点的小数部分 .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
.
有人能帮我理解吗?
1条答案
按热度按时间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就可以了。更好的方法是首先将其渲染为圆形字符串:
然后在绳子里找到你需要的东西。上面提到的是适当的四舍五入,它比使用math.pow做得更好,因为它会使你远离0,导致更多的错误出现(离0越远->更多的极端四舍五入错误,因为有更少的幸运数字)。
注:注意
double
它的速度和float一样快,而且假设你有64位可以在那里使用,它有更多的幸运数字,因此,错误更少。nb2:另一种方法是将你的“单位”概念转移。例如,如果这代表现金,只需
int cents;
-没有问题,知道祝福数字的意义就容易多了int
(介于-2^31和+2^31之间的每个整数)。