Java中计算双精度小数点后的位数的程序
下面是一个程序,用来计算小数点后双精度数值的位数。输入一些双精度值时,程序倾向于启动无限循环(可能是由于浮点不精确)。我不想使用任何包装器方法(包括String类)。有人能解释某些输入的无休止循环并提供解决方案吗
import java.util.*;
class Flt
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
System.out.print("Enter a double number: ");
double f = sc.nextDouble();
double tmp = f;
int len = 0;
while(tmp != (int) tmp)
{
tmp *= 10;
len++;
}
System.out.println(len);
}
}
# 1 楼答案
问题在转换为
int
时溢出,因此tmp != (int) tmp
永远不会为真考虑用户输入的“3.1415”。3.1415不能以
double
格式表示,因此它被转换为最接近的表示值3.141500000000000181188397618825547397136688232421875。首先,它有如此多的十进制数字,即使使用精确的实数运算执行十的乘法,它们也不会产生整数结果,直到数字达到3141500000000000181188397618825547397136688232421875。但是,如果没有溢出,则无法将该数字转换为int
,因为它太大,无法在int
中表示。转换产生的最大值以int
表示,2147483647。然后将数字3141500000000000181188397618825547397136688232421875与转换结果2147483647进行比较,表明它们不相等,循环继续事实上,十的乘法不是用精确的实数运算来完成的。在每次乘法中,结果四舍五入到
double
中表示的最接近的值。因此,第一个收益率为31.4150000000000027006239588380706310272216796875,下一个收益率为314.150000000003410605131648480892181396484375,依此类推。第一个整数结果是31415000000000004。同样,它太大,无法在int
中表示,因此tmp != (int) tmp
被计算为31415000000000004 != 2147483647
,这当然是正确的,因此循环继续无限循环可以通过消除到
int
的转换来解决。例如,测试表达式可以被tmp % 1 != 0
替换为循环,只要tmp
除以1时有余数(因此不是整数)。但是,如果输入“3.1415”,则产生16位。它不计算用户输入或扫描后的double
中的小数位数,而是计算迭代次数,直到四舍五入的乘法产生整数一旦用户的输入被转换为
double
,就无法正确计算用户输入的小数位数,因为原始值丢失了。如果用户输入“3.1415”或“3.141500000000000181188397618825547397136688232421875”,则生成的double
将是3.14150000000000011883976188255497136688232421875,因此无法判断原始数字是什么。要计算用户输入中的小数位数,请将其作为字符串读取,查找小数点,并计算小数点后的数字字符(如果需要,不包括尾随的零)