Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Are floating-point zeros required to stay exact?

Reply
Thread Tools

Are floating-point zeros required to stay exact?

 
 
army1987
Guest
Posts: n/a
 
      02-27-2013
Is this guaranteed to always work in all conforming implementations?

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
double zero = 0.;
if (zero == 0.) {
puts("Okay!");
return 0;
} else {
puts("Uh-oh!");
return EXIT_FAILURE;
}
}



--
[ T H I S S P A C E I S F O R R E N T ]
Troppo poca cultura ci rende ignoranti, troppa ci rende folli.
-- fathermckenzie di it.cultura.linguistica.italiano
<http://xkcd.com/397/>
 
Reply With Quote
 
 
 
 
Shao Miller
Guest
Posts: n/a
 
      02-27-2013
On 2/27/2013 14:56, army1987 wrote:
> Is this guaranteed to always work in all conforming implementations?
>
> #include <stdio.h>
> #include <stdlib.h>
> int main(void)
> {
> double zero = 0.;
> if (zero == 0.) {
> puts("Okay!");
> return 0;


Might as well've used 'EXIT_SUCCESS', there.

> } else {
> puts("Uh-oh!");
> return EXIT_FAILURE;
> }
> }
>


I'd say so, but I think you meant to ask if it would output "Okay!" on
all conforming implementations, which I'd also say "yes" to.

--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily," -- Richard Harter
 
Reply With Quote
 
 
 
 
James Kuyper
Guest
Posts: n/a
 
      02-27-2013
On 02/27/2013 02:56 PM, army1987 wrote:
> Is this guaranteed to always work in all conforming implementations?
>
> #include <stdio.h>
> #include <stdlib.h>
> int main(void)
> {
> double zero = 0.;
> if (zero == 0.) {
> puts("Okay!");
> return 0;
> } else {
> puts("Uh-oh!");
> return EXIT_FAILURE;
> }
> }


No.
"The accuracy of the floating-point operations (+, -, *, /) and of the
library functions in <math.h> and <complex.h> that return floating-point
results is implementation defined, as is the accuracy of the conversion
between floating-point internal representations and string
representations performed by the library functions in <stdio.h>,
<stdlib.h>, and <wchar.h>. The implementation may state that the
accuracy is unknown." (5.2.4.2.2p6)

In principle, that clause allows LDBL_MIN==LDBL_MAX to be true; only by
checking your implementation's documentation can you be sure that the
accuracy of your implementation is good enough for LDBL_MIN==LDBL_MAX to
be guaranteed false. In practice, floating point roundoff errors tend to
be proportional to the magnitude of the relevant values, so zero == 0.
should be exact on almost all implementations.

 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      02-27-2013
On 2/27/2013 15:29, James Kuyper wrote:
> On 02/27/2013 02:56 PM, army1987 wrote:
>> Is this guaranteed to always work in all conforming implementations?
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>> int main(void)
>> {
>> double zero = 0.;
>> if (zero == 0.) {
>> puts("Okay!");
>> return 0;
>> } else {
>> puts("Uh-oh!");
>> return EXIT_FAILURE;
>> }
>> }

>
> No.
> "The accuracy of the floating-point operations (+, -, *, /)


Which do not appear in the code.

> and of the
> library functions in <math.h> and <complex.h> that return floating-point
> results


Which do not appear in the code.

> is implementation defined, as is the accuracy of the conversion
> between floating-point internal representations


I do not see conversions happening in the code.

> and string
> representations performed by the library functions in <stdio.h>,
> <stdlib.h>, and <wchar.h>.


No library functions are using floating types in the code and there are
no string representations of a floating value in the code.

> The implementation may state that the
> accuracy is unknown." (5.2.4.2.2p6)
>
> [...Depends on above...]


--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily," -- Richard Harter
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-27-2013
On 2/27/2013 3:29 PM, James Kuyper wrote:
> On 02/27/2013 02:56 PM, army1987 wrote:
>> Is this guaranteed to always work in all conforming implementations?
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>> int main(void)
>> {
>> double zero = 0.;
>> if (zero == 0.) {
>> puts("Okay!");
>> return 0;
>> } else {
>> puts("Uh-oh!");
>> return EXIT_FAILURE;
>> }
>> }

>
> No.
> "The accuracy of the floating-point operations (+, -, *, /) and of the
> library functions in <math.h> and <complex.h> that return floating-point
> results is implementation defined, as is the accuracy of the conversion
> between floating-point internal representations and string
> representations performed by the library functions in <stdio.h>,
> <stdlib.h>, and <wchar.h>. The implementation may state that the
> accuracy is unknown." (5.2.4.2.2p6)


I don't think this paragraph applies. None of (+, -, *, /)
is performed, no library function from <math.h> or <complex.h> is
used, and there are no conversions from strings to floating-point.

Instead, I think we have to rely on 6.4.4.2p5:

"Floating constants are converted to internal format as
if at translation-time. [...] All floating constants of
the same source form shall convert to the same internal
format with the same value."

Thus, both appearances of `0.' produce the same value, and the
same value compares equal to itself. (In p7 we learn that the
value "should" be the same that the library would produce for a
conversion, but that's a "should" and not a "shall," and is in
a subsection titled "Recommended practice." I think it would be
hard to argue that p7's "should" brings 5.2.4.2.2p6 into play.)

I suppose that although both appearances of `0.' must produce
the same value, that value might not be "zero." If instead of
`if (zero == 0.)' the program had used `if (!zero)', perhaps it
is possible that "Uh-oh!" could be printed. On a really perverse
implementation, I imagine `0.' and `0.0' and `.0' and `0e0' and so
on could produce different values; it might be a QOI issue.

> In principle, that clause allows LDBL_MIN==LDBL_MAX to be true; only by
> checking your implementation's documentation can you be sure that the
> accuracy of your implementation is good enough for LDBL_MIN==LDBL_MAX to
> be guaranteed false. [...]


Could you explain your reasoning here? 5.2.4.2.2p{12,13}
require that LDBL_{MAX,MIN} be representable long double values,
hence, no round-off or approximation is involved. Also, `==' is
not in the list of operators whose accuracy is unspecified (and
indeed, floating-point `==' can be evaluated without any rounding
at all).

--
Eric Sosman
d
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      02-27-2013
On 02/27/2013 04:48 PM, Eric Sosman wrote:
> On 2/27/2013 3:29 PM, James Kuyper wrote:

....
>> "The accuracy of the floating-point operations (+, -, *, /) and of the
>> library functions in <math.h> and <complex.h> that return floating-point
>> results is implementation defined, as is the accuracy of the conversion
>> between floating-point internal representations and string
>> representations performed by the library functions in <stdio.h>,
>> <stdlib.h>, and <wchar.h>. The implementation may state that the
>> accuracy is unknown." (5.2.4.2.2p6)

>
> I don't think this paragraph applies. None of (+, -, *, /)
> is performed,


I've always assumed that "floating point operations" was the key phrase,
and that "(+, -, *, /)" should be taken only as examples, implying, in
particular, that the relational and equality operators were also
intended to be covered by that clause.

On the other hand, You might be right. If so, does that mean that the
unary +, unary -, !, ?:, ++, --, and compound assignment operators
acting on floating point values are also not covered, and must therefore
always return exact values? That's trivial to achieve for the first four
of those operators, but I don't think it's possible for the others - but
perhaps the others are covered by their definitions in terms of the four
explicitly-listed operations.

Still,

LDBL_MIN + LDBL_EPSILON == LDBL_MAX - LDBL_EPSILON

is unambiguously covered by that clause, and the same is true of

nextafterl(LDBL_MIN, 0.0) == nextafterl(LDBL_MAX,0.0)

and having either of those evaluate as true is an equally disconcerting
possibility.
 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      02-28-2013
On 2/27/2013 17:19, James Kuyper wrote:
> On 02/27/2013 04:48 PM, Eric Sosman wrote:
>> On 2/27/2013 3:29 PM, James Kuyper wrote:

> ...
>>> "The accuracy of the floating-point operations (+, -, *, /) and of the
>>> library functions in <math.h> and <complex.h> that return floating-point
>>> results is implementation defined, as is the accuracy of the conversion
>>> between floating-point internal representations and string
>>> representations performed by the library functions in <stdio.h>,
>>> <stdlib.h>, and <wchar.h>. The implementation may state that the
>>> accuracy is unknown." (5.2.4.2.2p6)

>>
>> I don't think this paragraph applies. None of (+, -, *, /)
>> is performed,

>
> I've always assumed that "floating point operations" was the key phrase,
> and that "(+, -, *, /)" should be taken only as examples, implying, in
> particular, that the relational and equality operators were also
> intended to be covered by that clause.
>
> On the other hand, You might be right. If so, does that mean that the
> unary +, unary -, !, ?:, ++, --, and compound assignment operators
> acting on floating point values are also not covered, and must therefore
> always return exact values? That's trivial to achieve for the first four
> of those operators, but I don't think it's possible for the others - but
> perhaps the others are covered by their definitions in terms of the four
> explicitly-listed operations.
>
> Still,
>
> LDBL_MIN + LDBL_EPSILON == LDBL_MAX - LDBL_EPSILON
>
> is unambiguously covered by that clause, and the same is true of
>
> nextafterl(LDBL_MIN, 0.0) == nextafterl(LDBL_MAX,0.0)
>
> and having either of those evaluate as true is an equally disconcerting
> possibility.
>


I seem to recall that 0 is special. It can be positive or negative, but
it is zero. It's not "imprecise zero," it's zero. The result of a
computation might or might not be zero, but there is no computation, here.

Consider 5.2.4.2.2p4's mention of "zero" alongside infinities and NaNs.
These three are all special. Also consider the alternative...
6.5.9p3 says that it'll be either true or false for a given pair. This
seems to suggest that the values matter, and the values are the same,
and having them compare as unequal would be nonsense.

--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily," -- Richard Harter
 
Reply With Quote
 
Les Cargill
Guest
Posts: n/a
 
      02-28-2013
James Kuyper wrote:
> On 02/27/2013 02:56 PM, army1987 wrote:
>> Is this guaranteed to always work in all conforming implementations?
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>> int main(void)
>> {
>> double zero = 0.;
>> if (zero == 0.) {
>> puts("Okay!");
>> return 0;
>> } else {
>> puts("Uh-oh!");
>> return EXIT_FAILURE;
>> }
>> }

>
> No.
> "The accuracy of the floating-point operations (+, -, *, /) and of the
> library functions in <math.h> and <complex.h> that return floating-point
> results is implementation defined, as is the accuracy of the conversion
> between floating-point internal representations and string
> representations performed by the library functions in <stdio.h>,
> <stdlib.h>, and <wchar.h>. The implementation may state that the
> accuracy is unknown." (5.2.4.2.2p6)
>
> In principle, that clause allows LDBL_MIN==LDBL_MAX to be true; only by
> checking your implementation's documentation can you be sure that the
> accuracy of your implementation is good enough for LDBL_MIN==LDBL_MAX to
> be guaranteed false. In practice, floating point roundoff errors tend to
> be proportional to the magnitude of the relevant values, so zero == 0.
> should be exact on almost all implementations.
>



If, for an implementation, it does not hold that "Okay!" is printed,
I would consider it strong evidence that no floating point should be
used for that implementation. If it must be used, then something
close to an exhaustive test suite would be required - which is another
way of saying "don't use floating point."

--
Les Cargill
 
Reply With Quote
 
Fred J. Tydeman
Guest
Posts: n/a
 
      02-28-2013
On Wed, 27 Feb 2013 21:48:59 UTC, Eric Sosman <> wrote:

> On a really perverse
> implementation, I imagine `0.' and `0.0' and `.0' and `0e0' and so
> on could produce different values; it might be a QOI issue.


You have listed four representations of zero.
At least two of them must have the same value.

6.4.4.2 Floating constants, paragraph 3 has:

For decimal floating constants,
and also for hexadecimal floating constants when FLT_RADIX is not a power of 2,
the result is either the nearest representable value,
or the larger or smaller representable value
immediately adjacent to the nearest representable value,
chosen in an implementation-defined manner.

So, any given source FP value can convert into one of three
representable values.

Annex F (if in effect) requires that all the various forms of zero
all convert to the same value.
---
Fred J. Tydeman Tydeman Consulting
Testing, numerics, programming
+1 (775) 287-5904 Vice-chair of PL22.11 (ANSI "C")
Sample C99+FPCE tests: http://www.tybor.com
Savers sleep well, investors eat well, spenders work forever.
 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      02-28-2013
On 2/27/2013 19:26, Les Cargill wrote:
> James Kuyper wrote:
>> On 02/27/2013 02:56 PM, army1987 wrote:
>>> Is this guaranteed to always work in all conforming implementations?
>>>
>>> #include <stdio.h>
>>> #include <stdlib.h>
>>> int main(void)
>>> {
>>> double zero = 0.;
>>> if (zero == 0.) {
>>> puts("Okay!");
>>> return 0;
>>> } else {
>>> puts("Uh-oh!");
>>> return EXIT_FAILURE;
>>> }
>>> }

>>
>> No.
>> "The accuracy of the floating-point operations (+, -, *, /) and of the
>> library functions in <math.h> and <complex.h> that return floating-point
>> results is implementation defined, as is the accuracy of the conversion
>> between floating-point internal representations and string
>> representations performed by the library functions in <stdio.h>,
>> <stdlib.h>, and <wchar.h>. The implementation may state that the
>> accuracy is unknown." (5.2.4.2.2p6)
>>
>> In principle, that clause allows LDBL_MIN==LDBL_MAX to be true; only by
>> checking your implementation's documentation can you be sure that the
>> accuracy of your implementation is good enough for LDBL_MIN==LDBL_MAX to
>> be guaranteed false. In practice, floating point roundoff errors tend to
>> be proportional to the magnitude of the relevant values, so zero == 0.
>> should be exact on almost all implementations.
>>

>
> If, for an implementation, it does not hold that "Okay!" is printed,
> I would consider it strong evidence that no floating point should be
> used for that implementation. If it must be used, then something
> close to an exhaustive test suite would be required - which is another
> way of saying "don't use floating point."
>


Is there any floating point representation where precise zero cannot be
represented? Strong evidence, indeed.

--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily," -- Richard Harter
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to count zeros in registers? Davy VHDL 39 12-05-2005 10:59 AM
Hexadecimal formatting with leading zeros?! Dmitry Bond. ASP .Net 1 10-13-2005 08:55 AM
Need help! I need to add lead zeros to a textbox Teep ASP .Net 2 06-21-2004 01:04 PM
Help! Need to add lead zeros to a textbox input TN Bella ASP .Net 6 06-21-2004 08:46 AM
Re: CSV for Excel - Problem with Leading Zeros Luke Zhang [MSFT] ASP .Net 0 06-26-2003 01:34 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57