java 浮动大于或小于零

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10386596/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 00:49:32  来源:igfitidea点击:

Float greater or less than zero

javaandroid

提问by mushroom

I have the following code which sometimes return as true and sometimes doesn't.

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

Any idea what might be causing the varying result?

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

The 0.00 string comes from a JSON object.

0.00 字符串来自 JSON 对象。

(code simplified)

(代码简化)

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

EDIT:

编辑:

What I have is some floats which I want to determine if its zero, less than zero or more than zero. The values could be stuff like 0.00, 0.001 or -0.001. How do I determine whether whether they are positive, negative or zero?

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

EDIT:

编辑:

Perhaps I should clarify how I get the values. I might be totally something else that is causing the problem because I read about BigDecimal and tried to use it to no avail.

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

The values are extracted from a JSON feed (which has this format LT:0.000) using this code:

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

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

Then to test if price is greater or less than zero, I used the following conditional statements:

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

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

This code is looped for many values read out from the JSON feed. And from the results, some pricewhich is zero gets processed as greater than zero and some gets processed as less than zero. I'm suspecting that something else is causing the problem here?

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

I also did a test to see if the problem was with the accuracy of the data. So I did this:

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

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

And for the zeros that got recognized as positives and negatives, the trace value for it was still 0.000000000000000000000000, not 0.000000000000000000000001or something like that.

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

回答by Jirka Hanika

Your expression will reliably produce a result of falsein Java.

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

However, suppose that the zero is, for example, the result of -1 divided by plus infinity. In this case it will be internally represented as, roughly said, -0.00. In some circumstances it will still be printed as a zero (without the minus sign), in others it will behave differently from 0.00.

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

Floats can generally be compared for less-than in the same way as integers - there is a risk of a rounding error, but that error is not helped by adding or subtracting a random small value. It is different with comparison for equality.

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

I suggest you double check your facts and do more readingabout floating point behavior.

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

Edit: I am greatly simplifying above to answer the original question. To answer the edit to the question, we need to go deeper.

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

For any operationon floating point numbers one should know and consider the precisionand accuracyof inputs, and the desired accuracyof the output. Sometimes the task is solvable and sometimes it is not - the input accuracy may not be sufficient to produce the answer.

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

In your case, the precisionis 32 bit, out of which 24 bits are the mantissa and 8 bits exponent. That means that this data type safely distinguishes 0.001 from 0.00100001 but not from 0.001000001 as you can easily see:

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

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

(Note that you would get a different result if you did not force single precision comparison by the casts. In that case the computation would be done in double precision and the numbers would be safely distinguished - until you bring them even closer together.)

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

So, precision is determined by the data type. Not so accuracy. Input accuracy is often much more challenging to determine than precision because it has nothing to do with the data type, except that accuracy can never be better than the precision.

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

A mathematical real number can find itself in four possible circumstances with regard to representability in a particular floating point type, and those correspond to different treatments that it receives when it occurs as a literal, in the human readable decimal notation.

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

  • It might be representable accurately in binary. For example, 0 or 0.25. Then it is as accurate as an integer would be in an integer variable.
  • Or it is approximately representable with accuracy corresponding to the type's precision. For example, 1/3 or 0.1 or 0.001. This happens when the exponent needed fits in the number of exponent bits available, but when the binary expansion of the number is either longer than the mantissa, or outright infinite.
  • Or it is approximately representable with drastically distorted accuracy. These are denormal(subnormal) numbers. It's not only inaccurate, arithmetics on it may slow down to a crawl, which is typically documented correct behavior, and even a respectable Java compiler may sweat a little upon seeing literals of this kind which is a however a bug.
  • Or it does not fit at all and compilers will refuse the literal as too large.
  • 它可能可以用二进制准确表示。例如,0 或 0.25。那么它就像整数变量中的整数一样准确。
  • 或者它可以近似地表示为对应于类型精度的精度。例如,1/3 或 0.1 或 0.001。当所需的指数适合可用的指数位数时,就会发生这种情况,但是当数字的二进制扩展长于尾数或完全无限时。
  • 或者它可以近似地以严重扭曲的精度表示。这些是非正规(次正规)数字。它不仅不准确,它的算术运算可能会慢到爬行,这通常被记录为正确的行为,即使是受人尊敬的 Java 编译器在看到这种文字时也可能会出汗,但这是一个错误
  • 或者它根本不适合,编译器会拒绝文字太大。

So, in your case, we have only three valid inputs: 0 (accurate), 0.001 (approximate) and -0.001 (approximate), and that makes your problem solvable. Simply compare your numbers with a 0 literal(which is accurate, by the way) and you will always get the expected boolean values(fully accurate output).

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

This however depends on your inputs being directly derived from literals. If your inputs were one of 0.001, -0.001 and (float)1000 * (float)0.001 - 1, this would be a different question and you would have to get the answers, for example like this:

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

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

And if you allow any inputs whatsoever, not just those three magic values, and have no clue about the input's accuracy, then that's just mission impossible. Even a literal starting as 0.000000000...with some garbage digits far down at the end will be converted by a Java compiler to a perfectly neutral zero, and after this happens, no amount of Java code will ever tell it from the accurate and beautiful 0.00, or from what happens if you add a minus sign to the underflowing value. It's all the same, inaccurate zero, the same bit pattern in your variable, rather than 3 distinct values.

如果您允许任何输入,而不仅仅是这三个魔法值,并且对输入的准确性一无所知,那么这就是不可能完成的任务。甚至0.000000000...以一些垃圾数字开头的文字也会被 Java 编译器转换为完全中性的零,在这种情况发生之后,再多的 Java 代码都无法分辨出它是从准确和美观0.00还是从什么如果您向下溢值添加一个减号,就会发生这种情况。变量中都是相同的、不准确的零、相同的位模式,而不是 3 个不同的值。

回答by dhaag23

Floats are inaccurate. You need to specify a margin of error, like:

浮动是不准确的。您需要指定误差幅度,例如:

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

回答by Jouni Aro

You can use Math.signum() to check if the value is equal to, less than or greater than zero.

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

回答by Tim Flinn

I did mine a bit different. I was expecting a sensor to show a reading of 1. This is what I came up with.

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

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