Violation of Conversion rule of C99.

R

Rajesh S R

Isn't this code violation of C99 standard?

#include <stdio.h>
int main( void )
{
float a = 0.7;

if(a < 0.7)
printf("Wrong");
else
printf("Right! God job");
return 0;
}



The output of the code is "wrong".

Isnt the output violating C99 standard which states:

*6.3.1.5 Real floating types*
When a float is promoted to double or long double, or a double is
promoted
to long double, its value is unchanged.

I am using DEV-CPP (MingW32) compiler for windows.

Thanks in advance for the reply.
 
E

Eric Sosman

Rajesh said:
Isn't this code violation of C99 standard?

#include <stdio.h>
int main( void )
{
float a = 0.7;

if(a < 0.7)
printf("Wrong");
else
printf("Right! God job");
return 0;
}



The output of the code is "wrong".

Isnt the output violating C99 standard which states:

*6.3.1.5 Real floating types*
When a float is promoted to double or long double, or a double is
promoted
to long double, its value is unchanged.

Right. But when a double is *de*moted to a float,
which happens in the initialization of `a', there is
no such guarantee.
 
W

William Hughes

Isn't this code violation of C99 standard?

#include <stdio.h>
int main( void )
{
float a = 0.7;

if(a < 0.7)
printf("Wrong");
else
printf("Right! God job");
return 0;

}

The output of the code is "wrong".

Isnt the output violating C99 standard which states:

*6.3.1.5 Real floating types*
When a float is promoted to double or long double, or a double is
promoted
to long double, its value is unchanged.

I am using DEV-CPP (MingW32) compiler for windows.

Thanks in advance for the reply.


No, the code appears to work correctly. Note that 0.7 is
a *double*. When you convert this to a float you get a slightly
smaller value (there is no float value that can hold
the double value). So a is now slightly smaller
than 0.7 double, and when you compare a to 0.7
a is promoted to double without changing its value so
you correctly get this result.
Try changing the comparison to "if(a < 0.7f)"

However, comparing floating point values for equality
is a mug's game. Even if you get things right it
is not worth the effort, and there is always the chance
(high probability) that some implementor will get
things wrong.


- William Hughes
 
R

Rajesh S R

Right. But when a double is *de*moted to a float,
which happens in the initialization of `a', there is
no such guarantee.

--
Eric Sosman
(e-mail address removed)- Hide quoted text -

- Show quoted text -

Thanks for the reply.
So due to demotion the value initialised is not represented exactly,
so you get the output as "wrong".
But C standard further states that:

If the value being converted is in the range of values that can be
represented but cannot be represented exactly, the result is either
the nearest higher or nearest lower representable value, chosen in an
*implementation-defined manner*.

So the output may also be "Right! God job" ,by some other compilers
and the output is implementation dependent.
Am I right?
 
W

William Hughes

Thanks for the reply.
So due to demotion the value initialised is not represented exactly,

Well the real number 0.7 can (very probably) not be represented
exactly as a double.
So inexactness is due to more than just the demotion. More precisely,
"due to demotion the value initialised is not the same as the value
of the real number 0.7 converted to a double."
so you get the output as "wrong".
But C standard further states that:

If the value being converted is in the range of values that can be
represented but cannot be represented exactly, the result is either
the nearest higher or nearest lower representable value, chosen in an
*implementation-defined manner*.

So the output may also be "Right! God job" ,by some other compilers
and the output is implementation dependent.
Am I right?

Yes. In this case even if the implementors get things right.

- William Hughes.
 
R

Richard Tobin

[/QUOTE]
If the value being converted is in the range of values that can be
represented but cannot be represented exactly, the result is either
the nearest higher or nearest lower representable value, chosen in an
*implementation-defined manner*.

So the output may also be "Right! God job" ,by some other compilers
and the output is implementation dependent.
Am I right?

You may well find that this happens if you use 0.8 instead of 0.7.

-- Richard
 
M

micans

However, comparing floating point values for equality
is a mug's game. Even if you get things right it
is not worth the effort, and there is always the chance
(high probability) that some implementor will get
things wrong.

I've noted that compilers (usually in some strict mode) even emit
warnings for comparing with 0.0. I have enough faith in implementors
that that seems too much of a stretch. Not to mention that there is no
other way to check for division-by-zero. I also think it will be
generally safe to compare with 1.0 (based on typical floating point
implementations).

Stijn
 
R

Richard Tobin

I've noted that compilers (usually in some strict mode) even emit
warnings for comparing with 0.0. I have enough faith in implementors
that that seems too much of a stretch. Not to mention that there is no
other way to check for division-by-zero.

Why would you want to check for division by zero? Wouldn't
division-by-anything-small-enough-to-cause-overflow usually be just as
bad?
I also think it will be
generally safe to compare with 1.0 (based on typical floating point
implementations).

Why is 1.0 any better than, say, 3.5? Both have exact binary
floating-point representations.

-- Richard
 
M

micans

Why would you want to check for division by zero? Wouldn't
division-by-anything-small-enough-to-cause-overflow usually be just as
bad?

In my work, the first is inmeasurably more common than the latter.
Think of computing an average where there the number of summands is
zero.
Why is 1.0 any better than, say, 3.5? Both have exact binary
floating-point representations.

It is not better. There are quite a lot of numbers that have exact
binary floating point representation, that goes without saying.

In my work, the number 1.0 somehow seems more common than 3.5 . YMMV.

Stijn
 
M

micans

In my work, the first is inmeasurably more common than the latter.
Think of computing an average where there the number of summands is
zero.

Probably someone is pointing this out in parallel, but in that case
the number being tested is likely of integer type, so my argument does
not make sense.

Stijn
 
M

micans

Why would you want to check for division by zero? Wouldn't
division-by-anything-small-enough-to-cause-overflow usually be just as
bad?

your stance make sense, yes. Going back to the code that generated the
warnings,
they were mostly in my sparse graph library, where zero values are not
stored.

Stijn
 
R

Rajesh S R

Well the real number 0.7 can (very probably) not be represented
exactly as a double.
So inexactness is due to more than just the demotion. More precisely,
"due to demotion the value initialised is not the same as the value
of the real number 0.7 converted to a double."




Yes. In this case even if the implementors get things right.

- William Hughes.- Hide quoted text -

- Show quoted text -

Thanks for the reply
But even the following code gives "Wrong".


int main(void)
{
float a = 0.7f;

if(a < 0.7)
printf("Wrong");
else
printf("God job");
return 0;
}

I think the explanation that the declaration
float a = 0.7f;
is equivalent to
float a = (float)0.7;/*Conversion from double to float might truncate
the result*/
will work.

The expression '0.7f' forces the compiler to interpret 0.7 as a float
directly, rather than as a double converted to float as clearly stated
by the standard.

So this explanation will fail.

So an explanation as you stated above, will work.
That is, the float value 0.7f can (very probably) not be represented
exactly as a float.

My question in this context is:
How this inaccurate representation complies with ANSI standards?

I hope my question is clear.
Please reply.

Thanks in advance for the reply.
 
R

Richard Tobin

Why would you want to check for division by zero? Wouldn't
division-by-anything-small-enough-to-cause-overflow usually be just as
bad?
[/QUOTE]
In my work, the first is inmeasurably more common than the latter.
Think of computing an average where there the number of summands is
zero.

Why would the number of summands be a floating point number? There's
no problem comparing integers with zero.
It is not better. There are quite a lot of numbers that have exact
binary floating point representation, that goes without saying.

In my work, the number 1.0 somehow seems more common than 3.5 . YMMV.

In my work, I rarely if ever fund myself comparing floating point
numbers with constants. But a floating point number that's supposed
to be 1.0 - or 3.5 - may well not be, even though those numbers can be
represented exactly.

In most cases where you can be sure that a floating point number will
be exactly what you want, you could have done it with integers
instead.

-- Richard
 
M

mark_bluemel

... even the following code gives "Wrong".

int main(void)
{
float a = 0.7f;

if(a < 0.7)

make this "if(a < 0.7f)" so that you are comparing float with float.
If you compare with "0.7", you first of all approximate 0.7 in a
double, then find the nearest float to this approximation, which is
not necessarily the nearest float to 0.7. (I think).
printf("Wrong");
Missing '\n' makes that less useful than I'd like.
else
printf("God job");
Missing '\n' and misspelling "Good" - unless you really meant "God".
return 0;

}

I'm not sure what you're trying to achieve. Some background reading on
floating-point representation may be more useful than experimentation
and posting to this newsgroup.
 
M

Mark McIntyre

Thanks for the reply
But even the following code gives "Wrong".


int main(void)
{
float a = 0.7f;

if(a < 0.7)
printf("Wrong");
else
printf("God job");
return 0;
}

Looks to me like you need to read Goldberg: "What Every Computer
Scientist Should Know About Floating-Point Arithmetic".

You can't reliably compare floating point data,especially of different
widths. C99
How this inaccurate representation complies with ANSI standards?

5.2.4.2.2 of the Standard specifically states that the accuracy is
implementaiton defined. That said, many implementations adhere to the
IEEE standard.

But there is no accurate representation anyway - see Goldberg.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
R

Rajesh S R

make this "if(a < 0.7f)" so that you are comparing float with float.
If you compare with "0.7", you first of all approximate 0.7 in a
double, then find the nearest float to this approximation, which is
not necessarily the nearest float to 0.7. (I think).


Missing '\n' makes that less useful than I'd like.> else

Missing '\n' and misspelling "Good" - unless you really meant "God".



I'm not sure what you're trying to achieve. Some background reading on
floating-point representation may be more useful than experimentation
and posting to this newsgroup.


I am aware about floating point representation a little.

My question is related with C!

My question is,
if the inaccurate representation violates C99 standards?
I guess nothing is said about accuracy or inaccurate representation in
C99 standards.

If nothing is said about something in a C99 document, is it
implementation dependent?

I hope I'm clear.
 
W

William Hughes

Thanks for the reply
But even the following code gives "Wrong".

int main(void)
{
float a = 0.7f;

if(a < 0.7)
printf("Wrong");
else
printf("God job");
return 0;

}

Unsurprisingly as a still has the value of 0.7 represented as a float
which
can be (and in this case is) smaller than 0.7 represented as a double.

try

int main(void)
{
float a = 0.7;

if(a < 0.7f)
printf("Wrong\n");
else
printf("Good job\n");
return 0;

}

or

int main(void)
{
float a = 0.7;

if(a < (double)((float)0.7))
printf("Wrong\n");
else
printf("Good job\n");
return 0;

}


I think the explanation that the declaration
float a = 0.7f;
is equivalent to
float a = (float)0.7;/*Conversion from double to float might truncate
the result*/
will work.

The expression '0.7f' forces the compiler to interpret 0.7 as a float
directly, rather than as a double converted to float as clearly stated
by the standard.

Yes, more precisely

According to the standard 0.7f must be the float value that best
approximates the
real number 0.7, or the second best or the third best. (float) 0.7
must be the
the float value that is the nearest value higher or the nearest value
lower to the value chosen for the double which
represents 0.7 (again the standard allows three possible choices).

So 0.7f does not have to equal (float)0.7 (however, Karnac is willing
to
bet that it does).
So this explanation will fail.

So an explanation as you stated above, will work.
That is, the float value 0.7f can (very probably) not be represented
exactly as a float.

No 0.7f (approx 0.699999988 on my machine)
is a possible float value
so it can with certainty be represented exactly as a float.
It is the real number 0.7 that ( very probably) can't be represented
exactly as a float. And very probably, the float value used to
represent the real number 0.7 (whether selected as 0.7f or as
(float)0.7)
will be smaller that the double value used to represent the
real number 0.7.

My question in this context is:
How this inaccurate representation complies with ANSI standards


The ANSI standards do not impose the restriction that every
decimal value be representable as a float and/or double
(this is not possible using base 2) or that every double value
be representable as a float value (this is usually not possible).
In general the float value used to represent x can be greater
than, less than or equal to the double value used to represent x.
(try 0.8, 0.7 and 0.5)

- William Hughes
 
U

user923005

Isn't this code violation of C99 standard?

#include <stdio.h>
int main( void )
{
float a = 0.7;

if(a < 0.7)
printf("Wrong");
else
printf("Right! God job");
return 0;

}

The output of the code is "wrong".

Isnt the output violating C99 standard which states:

*6.3.1.5 Real floating types*
When a float is promoted to double or long double, or a double is
promoted
to long double, its value is unchanged.

I am using DEV-CPP (MingW32) compiler for windows.

Thanks in advance for the reply.

Here is a clue:

C:\tmp>splint foo.c
Splint 3.0.1.6 --- 11 Feb 2002

foo.c: (in function main)
foo.c(7,8): Dangerous comparison involving float types: a < 0.7
Two real (float, double, or long double) values are compared
directly using a
C primitive. This may produce unexpected results since floating
point
representations are inexact. Instead, compare the difference to
FLT_EPSILON
or DBL_EPSILON. (Use -realcompare to inhibit warning)

Finished checking --- 1 code warning

For any comparison operation against floating point, we should imagine
(at best) a sphere of uncertainty of radius (FLT_EPSILON/DBL_EPSILON/
LDBL_EPSILON)*magnitude around the point in question (depending upon
type). Worse if the value is far from the origin.

It is also a mistake to imagine that we can take a double, push it
into a float, then reconstitute it as a double and have the same value
as the original. Clearly, that's not going to work. Once we shave
off the precision by stuffing a double into a float, those trailing
bits are gone -- floating off into the ether-bits.
 
T

Thad Smith

Rajesh said:
... even the following code gives "Wrong".
>>> [original code restored]
>>>
>>>#include <stdio.h>
int main(void)
{
float a = 0.7f;
>>>
if(a < 0.7)
printf("Wrong");
else
printf("God job");
return 0;
}

My question is,
if the inaccurate representation violates C99 standards?

Be precise. What "inaccurate representation" are you referring to? The
program above (after correcting for a missing header) may output either
"Wrong" or "God job") when run with a conforming implementation, so does
not illustrate a problem with C99, as has been explained by others.
I guess nothing is said about accuracy or inaccurate representation in
C99 standards.

Standard C specifies the minimum accuracy for representations in
standard floating point types. It says nothing, that I am aware of,
concerning the accuracy of calculations. If an implementation uses
IEEE-754, then a lot more can be said about the accuracy of
calculations, as well as representation.
If nothing is said about something in a C99 document, is it
implementation dependent?
Yes.

I hope I'm clear.

Alas, I don't know what specific inaccuracies you are questioning.
 
D

Dik T. Winter

>
> In my work, the first is inmeasurably more common than the latter.
> Think of computing an average where there the number of summands is
> zero.

The number of summands is an integer, not a floating point number.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,444
Messages
2,571,709
Members
48,796
Latest member
Greg L.
Top