漂浮大于或小于零

时间:2012-04-30 15:50:54

标签: java android

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

知道可能导致变化结果的原因是什么?

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 个答案:

答案 0 :(得分:3)

您的表达式将可靠地在Java中生成false的结果。

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

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

我建议你仔细检查一下你的事实和do more reading浮点行为。

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

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

在您的情况下,精度是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。当所需的指数与可用的指数位数相符,但当数字的二进制扩展比尾数长或完全无限时,就会发生这种情况。
  • 或者它具有严重失真的精确度。这些是denormal(次正规)数字。这不仅是不准确的,它上面的算术可能会减慢到爬行,这通常是记录正确的行为,甚至一个受人尊敬的Java编译器可能会因为看到这种类型的文字({3}}而出汗。
  • 或者根本不适合,编译器会拒绝文字太大。

因此,在您的情况下,我们只有三个有效输入: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个不同的值。

答案 1 :(得分:1)

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

float result = new Float("0.00");
float expected = 0;
if (Math.abs(result - expected) < 0.00001)
...

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我的确有点与众不同。我期待一个传感器显示读数为1.这就是我想出来的。

double a = y1;
                if((a-0)<1){
                    a=(1-a)+a;
                }