5

我有以下代码,有时返回为真,有时不返回。

知道什么可能导致不同的结果吗?

0.00 字符串来自 JSON 对象。

(代码简化)

if(new Float("0.00")>0){
    // do something
}

编辑:

我所拥有的是一些浮点数,我想确定它是零、小于零还是大于零。这些值可能是 0.00、0.001 或 -0.001。我如何确定它们是正数、负数还是零?

编辑:

也许我应该澄清我是如何获得这些价值观的。我可能完全是导致问题的其他原因,因为我阅读了 BigDecimal 并尝试使用它无济于事。

使用以下代码从 JSON 提要(格式为 LT:0.000)中提取值:

price = new BigDecimal(stocksJSONArray.getJSONObject(i).getString("LT"));

然后为了测试价格是大于还是小于零,我使用了以下条件语句:

if(price.compareTo(BigDecimal.ZERO)==1){
    // greater than zero
}
else if(price.compareTo(BigDecimal.ZERO)==-1){
    // less than zero
}

此代码循环用于从 JSON 提要中读取的许多值。从结果来看,一些price为零的被处理为大于零,一些被处理为小于零。我怀疑是其他原因导致了这里的问题?

我还做了一个测试,看看问题是否出在数据的准确性上。所以我这样做了:

DecimalFormat frmt = new DecimalFormat("0.000000000000000000000000");
String formatted = frmt.format(stock.change);

对于被识别为正数和负数的零,它的跟踪值仍然是0.000000000000000000000000,不是0.000000000000000000000001或类似的东西。

4

4 回答 4

4

您的表达式将可靠地产生falseJava 中的结果。

但是,假设零是例如 -1 除以正无穷大的结果。在这种情况下,它将在内部表示为,粗略地说,-0.00。在某些情况下,它仍将打印为零(没有减号),在其他情况下,它的行为与 0.00 不同。

通常可以以与整数相同的方式比较浮点数 - 存在舍入错误的风险,但添加或减去随机小值无助于该错误。与相等比较不同。

我建议您仔细检查您的事实并更多地阅读有关浮点行为的信息。

编辑:我在上面大大简化以回答原始问题。要回答对问题的编辑,我们需要更深入。

对于浮点数的任何运算,都应该知道并考虑输入的精度准确度,以及输出的所需准确度。有时任务是可解决的,有时则不是——输入的准确性可能不足以产生答案。

在您的情况下,精度为 32 位,其中 24 位是尾数和 8 位指数。这意味着此数据类型可以安全地将 0.001 与 0.00100001 区分开来,但不能与 0.001000001 区分开来,您可以很容易地看到:

 System.out.println((float)0.001 < (float)0.001000001);

(请注意,如果您不强制通过强制转换进行单精度比较,您将得到不同的结果。在这种情况下,计算将以双精度完成并且数字将被安全地区分 - 直到您将它们更接近。)

因此,精度由数据类型决定。没有那么准确。输入精度通常比精度更具挑战性,因为它与数据类型无关,只是精度永远不会比精度更好。

关于特定浮点类型的可表示性,数学实数可以在四种可能的情况下找到自己,并且这些情况对应于当它以人类可读的十进制表示法作为文字出现时所接受的不同处理。

  • 它可以用二进制准确表示。例如,0 或 0.25。那么它与整数变量中的整数一样准确。
  • 或者它可以近似地表示为与类型的精度相对应的精度。例如,1/3 或 0.1 或 0.001。当所需的指数适合可用的指数位数时,就会发生这种情况,但是当数字的二进制扩展长于尾数或完全无限时。
  • 或者它是近似可表示的,具有严重扭曲的准确性。这些是非正规(次正规)数。它不仅不准确,它的算术可能会慢到爬行,这通常记录了正确的行为,即使是一个受人尊敬的 Java 编译器也可能会在看到这种类型的文字时出汗,但这是一个错误
  • 或者它根本不适合,编译器会拒绝字面量太大。

因此,在您的情况下,我们只有三个有效输入:0(准确)、0.001(近似)和 -0.001(近似),这使您的问题可以解决。 只需将您的数字与 0 文字(顺便说一句,这是准确的)进行比较,您将始终获得预期的布尔值(完全准确的输出)。

然而,这取决于您的输入直接来自文字。如果您的输入是 0.001、-0.001 和 之一(float)1000 * (float)0.001 - 1,这将是一个不同的问题,您必须得到答案,例如:

if (-0.00001 < x && x < 0.00001) // then x is zero 

如果你允许任何输入,而不仅仅是这三个魔法值,并且不知道输入的准确性,那么这就是不可能完成的任务。即使是从末尾有一些垃圾数字开始的文字0.000000000...也会被 Java 编译器转换为完全中性的零,并且在这种情况发生之后,再多的 Java 代码都不会告诉它准确和漂亮0.00,或者从什么如果您在下溢值中添加减号,则会发生这种情况。都是一样的,不准确的零,变量中的相同位模式,而不是 3 个不同的值。

于 2012-04-30T16:02:52.613 回答
1

浮点数不准确。您需要指定误差范围,例如:

float result = new Float("0.00");
float expected = 0;
if (Math.abs(result - expected) < 0.00001)
...
于 2012-04-30T15:54:35.590 回答
1

您可以使用 Math.signum() 检查该值是否等于、小于或大于零。

于 2012-04-30T19:13:46.810 回答
0

我的做法有点不同。我期待一个传感器显示读数为 1。这就是我想出的。

double a = y1;
                if((a-0)<1){
                    a=(1-a)+a;
                }
于 2017-08-14T04:12:22.297 回答