提问人:millionleafclover 提问时间:9/27/2021 更新时间:9/28/2021 访问量:472
在 Java 中计算双后小数点的位数的程序
Program to count number of digits in a double following decimal point in 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);
}
}
答:
问题在转换为 时溢出,因此从来都不是真的。int
tmp != (int) tmp
考虑用户输入“3.1415”。3.1415 无法以格式表示,因此将其转换为最接近的可表示值 3.1415000000000000181188397618825547397136688232421875。首先,它有如此多的十进制数字,即使乘以 10 是用精确的实数算术执行的,它们也不会产生整数结果,直到数字达到 3141500000000000181188397618825547397136688232421875。但是,该数字不能转换为无溢出,因为它太大而无法用 .转换产生 2147483647 中可表示的最大值。然后,将3141500000000000181188397618825547397136688232421875数与转换结果(2147483647)进行比较,表明它们不相等,循环继续。double
int
int
int
事实上,乘以 10 并不是用精确的实数算术来执行的。在每次乘法中,结果都四舍五入到中可表示的最接近的值。因此,第一个生成 31.415000000000002700062395888380706310272216796875,接下来的产生 314.150000000000003410605131648480892181396484375,依此类推。第一个整数结果是 31415000000000004。同样,它太大而无法用 表示,因此被计算为 ,这当然是真的,所以循环继续。double
int
tmp != (int) tmp
31415000000000004 != 2147483647
无限循环可以通过消除到 的转换来解决。例如,测试表达式可以替换为 to 循环,只要除以 1 时有余数(因此不是整数)。但是,输入“3.1415”会产生 16 个 - 它不计算用户输入或扫描输入产生的小数位数,而是计算迭代次数,直到四舍五入的乘法产生整数。int
tmp % 1 != 0
tmp
double
一旦用户的输入被转换为 ,就无法正确计算用户输入中的小数位数,因为原始值丢失了。如果用户输入“3.1415”或“3.141500000000000181188397618825547397136688232421875”,则结果将是 3.141500000000000181188397618825547397136688232421875,因此无法分辨原始号码是什么。要计算用户输入中的小数位数,请将其作为字符串读取,查找小数点,并计算其后面的数字字符(如果需要,不包括尾随零)。double
double
评论
double
double
double
评论
BigDecimal
double
double