Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Eric Sosman Newsgroups: comp.lang.java.programmer Subject: Re: double == double Date: Wed, 12 Oct 2016 09:39:11 -0400 Organization: A noiseless patient Spider Lines: 66 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Wed, 12 Oct 2016 13:38:57 -0000 (UTC) Injection-Info: mx02.eternal-september.org; posting-host="3a7f4ea9fc2f59a681b15d6f0637dd2b"; logging-data="22002"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+zypChT62HttKhLrw5yIM7" User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 In-Reply-To: Cancel-Lock: sha1:1+5t78st9fDsZrNXL+ndx+FdxDo= Xref: csiph.com comp.lang.java.programmer:35750 On 10/12/2016 8:15 AM, Stefan Ram wrote: > Sometimes it is taught that it makes no sense to compare > two double values with »==«. That's an oversimplification, of course. > But what about this function? > > public static double max( final double a, final double b) > { return > a == 0.0 && b == 0.0 && java.lang.Double.doubleToRawLongBits( a ) > == Double.doubleToRawLongBits( -0.0d )? b : a >= b ? a : b; } > > which tries to return positive zero if one argument is > positive zero and the other one negative zero? The function could be simplified by eliminating the `a == 0.0' comparison. In fact, a further simplification is possible: public static double max(double a, double b) { return Math.max(a, b); } > It seems that there are special cases when a comparison > of double values with »==« is appropriate. I have observed > that this is usually the case when comparing with »0.0« - > another example would be avoiding to divide by 0.0. The problem with comparing double or float values for equality (or inequality) isn't the values themselves, but their "provenance." Calculations that yield identical results when performed with real numbers and their infinite precision may yield different outcomes when finite-precision floating-point values are used instead. We know, for example, that `ln xy = ln x + ln y' for all positive x,y, yet we cannot rely on `Math.log(x*y) == Math.log(x) + Math.log(y)'. A rearrangement that appears innocuous can produce a result that is slightly different (sometimes more than "slightly!") from that of the original, and it's no simple matter to say which, if either, is "right." Going more deeply than the "provenance" of a value we might want to consider its "genesis:" Where did the original inputs to the calculation come from? Usually they represent measurements of some kind: mass, speed, income, time spent writing Usenet posts, whatever. Measurements are not infinitely precise; they are not even "finitely precise" to the limits of our understanding -- how tall are you, in Ångström units? Different people making "the same" measurement will get different answers, especially if they use different techniques or are measuring attributes of different instances. Start with these already- approximate measures, run them through a chain of approximating calculations, and it makes little sense to expect exact equality of outcomes. It may be worth knowing that the average height of forty-two Swedish teenagers is greater than that of thirty-nine Ethiopians, but it is silly to ask whether the difference is "exactly" one centimeter. Finally, as to avoiding division by zero: Yes, an exactly-zero test can avoid it. But that still isn't armor against a meaningless result! If you divide a very large number by a very small one, even if the latter is not exactly zero, you may wind up with a result that floating-point arithmetic will call "infinite." In other words, even a non-zero divisor can lead to the loss of *all* significant digits in the supposed "answer." -- esosman@comcast-dot-net.invalid The Tooth Fairy has gone high-tech, now pays in Bitecoin.