Using type prefixes with floating point constants

Discussion in 'C Programming' started by Ioannis Vranos, Mar 26, 2009.

1. Ioannis VranosGuest

ISO/IEC 9899:1990/1995 says (from K&R2):

“A6.4

When a less precise floating value is converted to an equally or more
precise floating type, the value is unchanged.

==> When a more precise floating value is converted to a less precise floating type, and the value is within
representable range, the result may be either the next higher or the next lower representable value.

If the result is out of range, the behavior is undefined”.

Question: Does the above mean that it is a good practice or *always*
needed to use the appropriate type suffixes with floating point constants?

An example of this:

#include <stdio.h>

int main(void)
{
float f1 = 0.33439F;

float f2= 0.33439f;

printf("\nf1= %f, f2= %f\n", f1, f2);

double d1= 0.33439;

double d2= 0.33439;

printf("\nd1= %f, d2= %f\n", d1, d2);

/* It doesn't work with MINGW, compiler is broken regarding long double. */
long double ld1= 0.33439L;

long double ld2= 0.33439l; /* 'l' is the lower case 'L'. */

printf("\nld1= %Lf, ld2= %Lf\n\n", ld1, ld2);

return 0;
}

Ioannis Vranos, Mar 26, 2009

2. Barry SchwarzGuest

On Thu, 26 Mar 2009 16:48:10 +0200, Ioannis Vranos
<> wrote:

>ISO/IEC 9899:1990/1995 says (from K&R2):
>
>“A6.4
>
>When a less precise floating value is converted to an equally or more
>precise floating type, the value is unchanged.
>
>==> When a more precise floating value is converted to a less precise floating type, and the value is within
>representable range, the result may be either the next higher or the next lower representable value.
>
>If the result is out of range, the behavior is undefined”.
>
>
>Question: Does the above mean that it is a good practice or *always*
>needed to use the appropriate type suffixes with floating point constants?
>
>
>An example of this:
>
>
>#include <stdio.h>
>
>
>int main(void)
>{
> float f1 = 0.33439F;

If 0.33439 can be represented exactly in a float, it can also be
represented exactly in a double. In that case, the above code has the
same effect whether the F is present or not.

If 0.33439 cannot be represented exactly in a float, the constant on
the right hand side will be the appropriate float approximation (the
next higher or the next lower representable value). If the F were not
present, the constant on the right hand side would be the appropriate
double approximation (or possibly the exact representation) and when
it is assigned to f1 it will be adjusted to the next higher or the
next lower representable value. I imagine it is possible that a
perverse compiler could choose the lower approximation when the F is
present and the higher approximation when the F is not present.

About the only real benefit for the F is that without it some
compilers (and probably some lint tools) will issue diagnostics
regarding the possible loss of significance.

On the other hand,
float f1 = 0.123456; /*with or without the F*/
float f2 = f1 +0.33439F;
will perform the arithmetic on floats but without the F on the
constant would perform the arithmetic on doubles. This could impact
performance. More importantly, at the edges of significance it could
result is slightly different results.

On the third hand, almost all floating point values are approximations
and should be treated as such.

--
Remove del for email

Barry Schwarz, Mar 27, 2009

3. Ioannis VranosGuest

Barry Schwarz wrote:
> On Thu, 26 Mar 2009 16:48:10 +0200, Ioannis Vranos
> <> wrote:
>
>> ISO/IEC 9899:1990/1995 says (from K&R2):
>>
>> “A6.4
>>
>> When a less precise floating value is converted to an equally or more
>> precise floating type, the value is unchanged.
>>
>> ==> When a more precise floating value is converted to a less precise floating type, and the value is within
>> representable range, the result may be either the next higher or the next lower representable value.
>>
>> If the result is out of range, the behavior is undefined”.
>>
>>
>> Question: Does the above mean that it is a good practice or *always*
>> needed to use the appropriate type suffixes with floating point constants?
>>
>>
>> An example of this:
>>
>>
>> #include <stdio.h>
>>
>>
>> int main(void)
>> {
>> float f1 = 0.33439F;

>
> If 0.33439 can be represented exactly in a float, it can also be
> represented exactly in a double. In that case, the above code has the
> same effect whether the F is present or not.
>
> If 0.33439 cannot be represented exactly in a float, the constant on
> the right hand side will be the appropriate float approximation (the
> next higher or the next lower representable value). If the F were not
> present, the constant on the right hand side would be the appropriate
> double approximation (or possibly the exact representation) and when
> it is assigned to f1 it will be adjusted to the next higher or the
> next lower representable value. I imagine it is possible that a
> perverse compiler could choose the lower approximation when the F is
> present and the higher approximation when the F is not present.
>
> About the only real benefit for the F is that without it some
> compilers (and probably some lint tools) will issue diagnostics
> regarding the possible loss of significance.
>
> On the other hand,
> float f1 = 0.123456; /*with or without the F*/
> float f2 = f1 +0.33439F;
> will perform the arithmetic on floats but without the F on the
> constant would perform the arithmetic on doubles. This could impact
> performance. More importantly, at the edges of significance it could
> result is slightly different results.
>
> On the third hand, almost all floating point values are approximations
> and should be treated as such.

"Corrected: Using type suffixes with floating point constants"

Ioannis Vranos, Mar 27, 2009
4. Dik T. WinterGuest

In article <> Barry Schwarz <> writes:
....
> If 0.33439 cannot be represented exactly in a float, the constant on
> the right hand side will be the appropriate float approximation (the
> next higher or the next lower representable value). If the F were not
> present, the constant on the right hand side would be the appropriate
> double approximation (or possibly the exact representation) and when
> it is assigned to f1 it will be adjusted to the next higher or the
> next lower representable value. I imagine it is possible that a
> perverse compiler could choose the lower approximation when the F is
> present and the higher approximation when the F is not present.

A compiler need not be perverse if this happens. It can occur with standard
IEEE arithmetic. In the first case there is only one rounding involved:
round to float, in the second case there are two roundings involved, first
to double and next to float. It is well known that the two do not necessarily
give the same result.
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

Dik T. Winter, Mar 27, 2009
5. Keith ThompsonGuest

Ioannis Vranos <> writes:
[...]
>
> "Corrected: Using type suffixes with floating point constants"
>

It would have been good to indicate just what you were correcting.
Apparently you just changed "prefixes" to "suffixes" in the subject
header, but I didn't take the time to compare the two articles to see
if anything eles changed.

on the same topic is rarely a good idea. In this case, it would have
been better to post a correction on the original thread and live with
the incorrect subject line.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson, Mar 27, 2009