Corrected: Using type suffixes with floating point constants

I

Ioannis Vranos

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 <iostream>


int main(void)
{
using namespace std;

float f1 = 0.33439F;

float f2= 0.33439f;

cout<< "\nf1= "<< f1<<", f2= "<< f2<< endl;


double d1= 0.33439;

double d2= 0.33439;

cout<< "\nd1= "<< d1<<", d2= "<< d2<< endl;


// 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'.

cout<< "\nld1= "<< ld1<<", ld2= "<< ld2<< endl;


return 0;
}
 
V

Victor Bazarov

Ioannis said:
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?

No, the above does not mean that. You need to look at the definition of
the FP literals. The suffix only says what type the literal has. The
suffix does not control potential precision. IOW

float Pi = 3.1415926;
float Pi_ = 3.1415926f;

will *likely* have the same value since the number of digits (8) in the
literals is greater than 'float' can represent (7), and both numbers
will be "fixed", only at different times, so to speak. The former will
be squeezed into a 'float' at the time of initialising of 'Pi' (formally
by your program), the other will be squeezed into a 'float' by the
compiler upon creating the literal. It is conceivable that the numbers
will be different *if* your compiler uses a different way of "fixing" of
the value to fit into a 'float' than your program (which can actually be
controlled in some cases by a flag in the CPU/FPU, IIRC).
An example of this:

An example of *what* exactly? That it's a good idea to always use the
suffixes?
#include <iostream>


int main(void)
{
using namespace std;

float f1 = 0.33439F;

float f2= 0.33439f;

cout<< "\nf1= "<< f1<<", f2= "<< f2<< endl;


double d1= 0.33439;

double d2= 0.33439;

cout<< "\nd1= "<< d1<<", d2= "<< d2<< endl;


// 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'.

cout<< "\nld1= "<< ld1<<", ld2= "<< ld2<< endl;


return 0;
}

V
 
J

James Kanze

[...]
No, the above does not mean that. You need to look at the
definition of the FP literals. The suffix only says what type
the literal has. The suffix does not control potential
precision. IOW
float Pi = 3.1415926;
float Pi_ = 3.1415926f;
will *likely* have the same value since the number of digits
(8) in the literals is greater than 'float' can represent (7),
and both numbers will be "fixed", only at different times, so
to speak.

First, as you know, a float can have more than 8 decimal digits
of precision. I'll suppose that we're talking about the usual
IEEE float here.
The former will be squeezed into a 'float' at the time of
initialising of 'Pi' (formally by your program), the other
will be squeezed into a 'float' by the compiler upon creating
the literal. It is conceivable that the numbers will be
different *if* your compiler uses a different way of "fixing"
of the value to fit into a 'float' than your program (which
can actually be controlled in some cases by a flag in the
CPU/FPU, IIRC).

The big difference is that formally, the first involves two
roundings: decimal to double, then double to float. This
certainly could, in certain cases, result in a difference in the
LSB.
 
I

Ioannis Vranos

Victor said:
No, the above does not mean that. You need to look at the definition of
the FP literals. The suffix only says what type the literal has. The
suffix does not control potential precision. IOW

float Pi = 3.1415926;
float Pi_ = 3.1415926f;

will *likely* have the same value since the number of digits (8) in the
literals is greater than 'float' can represent (7), and both numbers
will be "fixed", only at different times, so to speak. The former will
be squeezed into a 'float' at the time of initialising of 'Pi' (formally
by your program), the other will be squeezed into a 'float' by the
compiler upon creating the literal. It is conceivable that the numbers
will be different *if* your compiler uses a different way of "fixing" of
the value to fit into a 'float' than your program (which can actually be
controlled in some cases by a flag in the CPU/FPU, IIRC).



The sizes differ:


#include <stdio.h>


int main(void)
{
printf("sizeof(0.33439F)= %lu, sizeof(0.33439)= %lu\n\n",
(unsigned long)sizeof(0.33439F), (unsigned long)sizeof(0.33439));


return 0;
}


john@ubuntu:~/Projects/anjuta/c/src$ ./foobar
sizeof(0.33439F)= 4, sizeof(0.33439)= 8

john@ubuntu:~/Projects/anjuta/c/src$
 
I

Ioannis Vranos

Victor said:
No, the above does not mean that. You need to look at the definition of
the FP literals. The suffix only says what type the literal has. The
suffix does not control potential precision. IOW

float Pi = 3.1415926;
float Pi_ = 3.1415926f;

will *likely* have the same value since the number of digits (8) in the
literals is greater than 'float' can represent (7), and both numbers
will be "fixed", only at different times, so to speak. The former will
be squeezed into a 'float' at the time of initialising of 'Pi' (formally
by your program), the other will be squeezed into a 'float' by the
compiler upon creating the literal. It is conceivable that the numbers
will be different *if* your compiler uses a different way of "fixing" of
the value to fit into a 'float' than your program (which can actually be
controlled in some cases by a flag in the CPU/FPU, IIRC).


The sizes differ in my system:


#include <iostream>


int main(void)
{
using namespace std;

cout<<"sizeof(0.33439F)= "<< sizeof(0.33439F)<< ", sizeof(0.33439)= "
<<sizeof(0.33439)<<endl<< endl;


return 0;
}


john@ubuntu:~/Projects/anjuta/cpp/src$ ./foobar
sizeof(0.33439F)= 4, sizeof(0.33439)= 8

john@ubuntu:~/Projects/anjuta/cpp/src$
 
I

Ioannis Vranos

Forwarded:


(e-mail address removed) said:

I don't know about best practice---I don't use floating point often
enough for that---, but it certainly is not needed to always specify
the suffixes.

First of all, the majority of floating point constants are not exactly
representable in any of the floating point types, so you get the
conversion to the next higher or next lower representable value
anyway.
If float and double don't have the same range and precision, then a
compiler must be really perverse to get different results for the
expressions '(float)0.33439' and '0.33439F'.

The only suffix with more than documentary value is L (or l), if you
need the extra precision or range that long double might give you.

Bart v Ingen Schenau
 
I

Ioannis Vranos

Ioannis said:
Forwarded:


(e-mail address removed) said:


I don't know about best practice---I don't use floating point often
enough for that---, but it certainly is not needed to always specify
the suffixes.

First of all, the majority of floating point constants are not exactly
representable in any of the floating point types, so you get the
conversion to the next higher or next lower representable value
anyway.
If float and double don't have the same range and precision, then a
compiler must be really perverse to get different results for the
expressions '(float)0.33439' and '0.33439F'.

The only suffix with more than documentary value is L (or l), if you
need the extra precision or range that long double might give you.

Bart v Ingen Schenau


Yes I think there is a case for long doubles constants. If we use the default double constants we may loose
both in precision and value ranges, on assignment to a long double variable and at calculations.


However I think we also have a case for floats, for truncation and perhaps compiler range checks.
 
V

Victor Bazarov

Ioannis said:
The sizes differ in my system:


#include <iostream>


int main(void)
{
using namespace std;

cout<<"sizeof(0.33439F)= "<< sizeof(0.33439F)<< ", sizeof(0.33439)= "
<<sizeof(0.33439)<<endl<< endl;


return 0;
}


john@ubuntu:~/Projects/anjuta/cpp/src$ ./foobar
sizeof(0.33439F)= 4, sizeof(0.33439)= 8

john@ubuntu:~/Projects/anjuta/cpp/src$

Ahem... If there weren't different, why would we have this
conversation, right? Of course they are different. But what does this
have to do with the issue at hand? You're asking about initialising a
'float' with either an explicit 'float' literal or with a 'double'
literal. I am saying that there would be most likely no difference *for
the resulting 'float'*.

V
 
V

Victor Bazarov

Ioannis said:
Because of the unavoidable mistakes, typos and other, and also to keep
track how the proposal evolves, I have created a web page for it:

http://www.cpp-software.net/documents/cpp_only_proposal.html


So please base your answers to that document.

Please amend your proposal with the description of the problems you're
trying to solve. "Increase type safety" reads like hand waving, it's
too generic. Please don't repeat by stating what the mechanism would
do, I think by now we all get it. Explain *why* you want conversions to
be ignored in certain cases, and what prevents you from solving those
problems using the existing mechanisms in the language. Thanks!

V
 

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

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top