static_cast<unsigned int> question...

G

GuineaPig

Hello,

I'm (very) new to c++ and I'm having trouble understanding why this doesn't
work. Here's some testcode:

#include <iostream.h>

int main()
{
float test;
unsigned int test2;
test = 1.8;
cout << "\n" << test*100.0 << endl;
test2 = static_cast<unsigned int>(test*100.0);
cout << "\n" << test2 << endl;

}


The strange thing is that the program returns 180 on the first cout (as
expected) but it returns 179 on the second ???
If I make test 1.7, I get 170 on the first and second cout ???
I tried a whole bunch of other values... Sometimes I'm getting what I
expected, sometimes not...

Can anyone explain this to me ?

Tnx in advance,

Tom
 
F

Fraser Ross

Its nothing to do with static_cast and it is not needed.

test2 = static_cast<unsigned int>(test*100.0);


Probably your processor only does 64 bit floating point. float is 32bit.
The float of 1.8 is converted to a double of something like 1.7999999513.

The standard says:
The values of the floating operands and the results of floating
expressions may be represented in greater precision and range than
that required by the type; the types are not changed thereby

The truncation to unsinged int made the loss of precision.

Fraser.
 
K

Karl Heinz Buchegger

GuineaPig said:
Hello,

I'm (very) new to c++ and I'm having trouble understanding why this doesn't
work. Here's some testcode:

#include <iostream.h>

int main()
{
float test;
unsigned int test2;
test = 1.8;
cout << "\n" << test*100.0 << endl;
test2 = static_cast<unsigned int>(test*100.0);
cout << "\n" << test2 << endl;

}

The strange thing is that the program returns 180 on the first cout (as
expected) but it returns 179 on the second ???

That's because you computer cannot store the value 1.8 exactly.
It may be stored as 1.7999999999999999... or 1.80000000000001 or
something like that.

Multiplying with 100 gives 179.9999999999999999... or
180.0000000000001 or something like that.

When operator<< outputs a floating point number, this number is
rounded to x decimal digits (usually x equals 6, if nothing else specified).
So rounding 179.99999999999999 to 6 digits yields (surprise) 180.000000
Rounding 180.00000000000001 to six digits also yields 180.000000
(and of course the superflous decimal digits are not output).

Note: The number was *rounded* in order to be printed.

The cast does a very different thing. The cast truncates the
decimal digits from a number.

179.9999999999999999 is close to 180.0, but that doesn't
matter. Truncating the decimal digits still leaves you with
179.

180.0000000000000001 is also close to 180.0, but this time
truncating the decimal digits leaves you with 180.

The difference: rounding gives a different result then truncating.
If I make test 1.7, I get 170 on the first and second cout ???
I tried a whole bunch of other values... Sometimes I'm getting what I
expected, sometimes not...

It depends on how the numbers are stored. Note: A computer cannot
store every floating point number exactly. In the range 0 .. 1
there are indefinitly many floating point numbers and your computer
only has a finite memory.
 
P

Peter van Merkerk

I'm (very) new to c++ and I'm having trouble understanding why this
doesn't
work. Here's some testcode:

#include <iostream.h>

int main()
{
float test;
unsigned int test2;
test = 1.8;
cout << "\n" << test*100.0 << endl;
test2 = static_cast<unsigned int>(test*100.0);
cout << "\n" << test2 << endl;

}

The strange thing is that the program returns 180 on the first cout (as
expected) but it returns 179 on the second ???
If I make test 1.7, I get 170 on the first and second cout ???
I tried a whole bunch of other values... Sometimes I'm getting what I
expected, sometimes not...

Can anyone explain this to me ?

This is caused by the way the float type store number internally. Some
numbers cannot be exactly represented in floating point format; only a
approximation of the number is stored. Because of this 1.8*100.0 may
produce 179.9999952. The reason you see 180.000 is because the result is
rounded before it is printed. When you change the line that outputs the
floating point value to:

cout << "\n" << std::setprecision(10) << test*100.0 << endl;

You will probably see that test*100.0 is not exactly 180.0

When casting to in the part behind the decimal point will be truncated
so the result will be 179.

This is also the reason why comparing two floating point values with the
== operator is usually wrong. For example the program below will (most
likely) output the text "Not equal", because the number 1.23 cannot be
exactly represented in IEEE-754 floating point format (which most
implementations use for floating point numbers):

#include <iostream>
int main()
{
float f = 1.23;

if(f*2 == 2.46)
{
std::cout << "Equal\n";
}
else
{
std::cout << "Not Equal\n";
}

return 0;
}
 
L

Li Fanxi

GuineaPig said:
Hello,

I'm (very) new to c++ and I'm having trouble understanding why this doesn't
work. Here's some testcode:

#include <iostream.h>

int main()
{
float test;
unsigned int test2;
test = 1.8;
cout << "\n" << test*100.0 << endl;
test2 = static_cast<unsigned int>(test*100.0);
cout << "\n" << test2 << endl;

}


The strange thing is that the program returns 180 on the first cout (as
expected) but it returns 179 on the second ???
If I make test 1.7, I get 170 on the first and second cout ???
I tried a whole bunch of other values... Sometimes I'm getting what I
expected, sometimes not...

Can anyone explain this to me ?

Tnx in advance,

Tom

Because float is not an accurate data type.
For example, an integer 1 add up for 1000 times, you get 1000, but if
you add float 0.1 for 1000 times, you may get 99.999, not 100.
 
R

Ron Natalie

Li Fanxi said:
Because float is not an accurate data type.

It pains me when people say this. It leads people to believe that there is some
non-deterministic thing going on with floats. They're perfectly accurate. The issue
is not all rational numbers are representable accurately. The confusing issue is that
while people understand that 1/3 isn't precisely representable in a finite precision
decimal, they don't undertand that .1 is NOT precisely representable in binary.
For example, an integer 1 add up for 1000 times, you get 1000, but if
you add float 0.1 for 1000 times, you may get 99.999, not 100.

..1 is converted to one of the two nearest representable float values which
is implementation specific. From then on, the result is deterministic. You
get 1000 * whatever the converted value is.
 
R

Rolf Magnus

Ron said:
.1 is converted to one of the two nearest representable float values
which
is implementation specific. From then on, the result is
deterministic. You get 1000 * whatever the converted value is.

"1000 * whatever the converted value is" might also not be
representable.
 
T

Tim Slattery

Ron Natalie said:
It pains me when people say this. It leads people to believe that there is some
non-deterministic thing going on with floats. They're perfectly accurate. The issue
is not all rational numbers are representable accurately. The confusing issue is that
while people understand that 1/3 isn't precisely representable in a finite precision
decimal, they don't undertand that .1 is NOT precisely representable in binary.

It's also true that floating point numbers are limited in their
precision. It will happily store a 45-digit number for you, but as
(maybe) 1.3456789 time 10 to the 45 power. Digits in excess of the
precision limit are (I think) lopped off with no error being
generated.
 
R

Ron Natalie

Tim Slattery said:
It's also true that floating point numbers are limited in their
precision. It will happily store a 45-digit number for you, but as
(maybe) 1.3456789 time 10 to the 45 power. Digits in excess of the
precision limit are (I think) lopped off with no error being
generated.
If you're trying to equate decimal digits as some metric of precision you're
going to be disappointed.
 
F

Fraser Ross

"Ron Natalie"
If you're trying to equate decimal digits as some metric of precision you're
going to be disappointed.

I've seen float described as having 7 digit precision and double has 15.

Fraser.
 

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
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top