简体   繁体   English

漂浮大于或小于零

[英]Float greater or less than zero

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. 值可以是0.00,0.001或-0.001之类的值。 How do I determine whether whether they are positive, negative or zero? 如何确定它们是正面还是负面?

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. 此代码循环使用从JSON提要读取的许多值。 And from the results, some price which is zero gets processed as greater than zero and some gets processed as less than zero. 从结果中,一些零price被处理为大于零,一些价格被处理为小于零。 I'm suspecting that something else is causing the problem here? 我怀疑还有其他因素导致这个问题吗?

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.000000000000000000000001 or something like that. 对于被识别为正面和负面的零点,它的跟踪值仍然是0.000000000000000000000000 ,而不是0.000000000000000000000001或类似的东西。

Your expression will reliably produce a result of false in Java. 您的表达式将在Java中可靠地生成false结果。

However, suppose that the zero is, for example, the result of -1 divided by plus infinity. 但是,假设零是例如-1除以无穷大的结果。 In this case it will be internally represented as, roughly said, -0.00. 在这种情况下,它将在内部表示为,粗略地说,-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. 在某些情况下,它仍将打印为零(没有减号),在其他情况下,它的行为与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 reading about 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 operation on floating point numbers one should know and consider the precision and accuracy of inputs, and the desired accuracy of 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 precision is 32 bit, out of which 24 bits are the mantissa and 8 bits exponent. 在您的情况下, 精度为32位,其中24位是尾数,8位是指数。 That means that this data type safely distinguishes 0.001 from 0.00100001 but not from 0.001000001 as you can easily see: 这意味着此数据类型可以安全地区分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. 例如,0或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. 例如,1/3或0.1或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 . 这不仅是不准确的,它上面的算术可能会减慢到爬行,这通常是记录正确的行为,甚至一个受人尊敬的Java编译器可能会因为看到这种类型的文字而出汗,但这是一个错误
  • Or it does not fit at all and compilers will refuse the literal as too large. 或者根本不适合,编译器会拒绝文字太大。

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

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. 即使文字起始为0.000000000...一些垃圾数字也会被Java编译器转换为完全中性的零,并且在此之后,任何数量的Java代码都无法从准确和美丽的方面告诉它0.00 ,或者如果您向下溢值添加减号会发生什么。 It's all the same, inaccurate zero, the same bit pattern in your variable, rather than 3 distinct values. 它是完全相同的,不准确的零,变量中的相同位模式,而不是3个不同的值。

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)
...

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

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;
                }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM