浮动大于或小于零

mus*_*oom 5 java android

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

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

0.00 字符串来自 JSON 对象。

(代码简化)

if(new Float("0.00")>0){
    // do something
}
Run Code Online (Sandbox Code Playgroud)

编辑:

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

编辑:

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

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

price = new BigDecimal(stocksJSONArray.getJSONObject(i).getString("LT"));
Run Code Online (Sandbox Code Playgroud)

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

if(price.compareTo(BigDecimal.ZERO)==1){
    // greater than zero
}
else if(price.compareTo(BigDecimal.ZERO)==-1){
    // less than zero
}
Run Code Online (Sandbox Code Playgroud)

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

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

DecimalFormat frmt = new DecimalFormat("0.000000000000000000000000");
String formatted = frmt.format(stock.change);
Run Code Online (Sandbox Code Playgroud)

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

Jir*_*ika 4

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

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

通常可以按照与整数相同的方式比较浮点数是否小于 - 存在舍入误差的风险,但通过添加或减去随机小值并不能解决该错误。这与平等比较不同。

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

编辑:我极大地简化了上面的内容来回答原来的问题。要回答对问题的编辑,我们需要更深入。

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

在您的例子中,精度为 32 位,其中 24 位是尾数,8 位指数。这意味着该数据类型可以安全地区分 0.001 和 0.00100001,但不能区分 0.001000001,如您所见:

 System.out.println((float)0.001 < (float)0.001000001);
Run Code Online (Sandbox Code Playgroud)

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

因此,精度由数据类型决定。不太准确。输入精度通常比精度更难确定,因为它与数据类型无关,只是精度永远不可能比精度更好。

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

  • 它可以用二进制准确地表示。例如,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 
Run Code Online (Sandbox Code Playgroud)

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