我有一个接受数字的StreamTokenizer。但是,解析后的数字与输入的数字不同。
示例代码:
Web Hosting
输出:
String str = "1000000000000.0000000000000";
double initial = 1000000000000.0000000000000;
InputStream in = new ByteArrayInputStream(str.getBytes());
StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(in)));
input.parseNumbers();
int n = input.nextToken();
if (n == StreamTokenizer.TT_NUMBER) {
System.out.println("Original: " + str);
System.out.println("Parsed: " + input.nval);
System.out.println(initial + " == " + input.nval + " -> " + (initial == input.nval));
}
如何防止这种情况使两个Original: 1000000000000.0000000000000
Parsed: 9.999999999999999E11
1.0E12 == 9.999999999999999E11 -> false
值相等?
编辑:链接的问题讨论了为什么出现此问题。我在问有什么可能的方法来避免这个问题。
答案 0 :(得分:0)
根据David Conrad的分析,带有小数点的数字的StreamTokenizer
类处理是有缺陷的,并且似乎没有解决方法。
但这只是该类中许多缺点的不足之一。使用Scanner
或String.split
会更好。如果输入确实很复杂,请考虑使用解析器生成器来生成精确实现输入语法的词法分析器/解析器。
相关错误:
已经说过,使用浮点数的应用程序应该容忍由舍入误差和不精确性引起的问题。比较浮点数的最佳方法有很多问答。例如
答案 1 :(得分:0)
表示数字的确切方法是使用BigDecimal。 Double具有一定的精度,并且使用各种精度的double(EX:double1 = 10000.0和double2 = 0.0001)可能会导致0.0001下降。 BigDecimal避免了这种情况。
BigDecimal的缺点:
但是,如果您要花钱或必须精打细算,则应使用BigDecimal,否则会造成损失。 例如:
String str = "1.0E12";
double initial = 1000000000000.0000000000000;
BigDecimal exVal = new BigDecimal(str);
System.out.println("Original: " + str);
System.out.println("Parsed: " + exVal);
System.out.println(initial + " == " + exVal + " -> " + (initial == exVal.doubleValue()));
程序输出:
Original: 1.0E12
Parsed: 1.0E+12
1.0E12 == 1.0E+12 -> true