StreamTokenizer输入编号和解析的编号不同

时间:2018-08-15 03:06:01

标签: java token

我有一个接受数字的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 值相等?

编辑:链接的问题讨论了为什么出现此问题。我在问有什么可能的方法来避免这个问题。

2 个答案:

答案 0 :(得分:0)

根据David Conrad的分析,带有小数点的数字的StreamTokenizer类处理是有缺陷的,并且似乎没有解决方法。

但这只是该类中许多缺点的不足之一。使用ScannerString.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