C++ doubt

S

santosh

Hello,
I have two doubts on C++.
1. float i=1.1;
double d=1.1;
if(i==d)
printf("equal\n");
else
printf("not-equal\n");
what is the output?
I am getting "not-equal" as output.
Why it is so?
 
T

Teddy

This is a precision problem
For 2 float numbers you should use '>=' or '<=' operator, not '=='
operator to judge if they equal
 
P

Peter Koch Larsen

santosh said:
Hello,
I have two doubts on C++.
1. float i=1.1;
double d=1.1;
if(i==d)
printf("equal\n");
else
printf("not-equal\n");
what is the output?
I am getting "not-equal" as output.
Why it is so?
float and double are imprecise types and none of them can accurately
represent 1.1. When the float and the double get compared, the float is
first type-promoted to double. In this process, the difference between the
accuracy of the two types manifests itself: the two values are different.

/Peter
 
L

Larry I Smith

santosh said:
Hello,
I have two doubts on C++.
1. float i=1.1;
double d=1.1;
if(i==d)
printf("equal\n");
else
printf("not-equal\n");
what is the output?
I am getting "not-equal" as output.
Why it is so?

Both 'C' and 'C++' may output "not-equal" for this.

It has to do with how an infinite range of possible
values are represented in the limited bits available
to store the values. Most floating point values can
not be stored precisely using the binary representation
used in computers. Since 'float' and 'double' may be
different sizes (i.e. use differing number of binary
bits to hold their value), they each store a slightly
different value that approximates 1.1.

See the FAQ sections 29.16 and 29.17 for more details:

http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.16

Regards,
Larry
 
V

velthuijsen

You do not have two doubles, you have a float and a double.
Comparing two floats with each other or two doubles with each other is
tricky but comparing a float with a double the way you do is asking for
problems.

The following happens when you do if(i==d)
i is implicitly expanded to double size. The problem being that only
the first 8 decimals of i have a value (1.1000000 should be about
right) a double has a precision of (at least) 16 decimals so you end up
with a number 1.1000000???????? where the questionmarks can be anything
between 00000000 and 49999999 because 1.1 does not fit perfectly in the
double (or float) binary format so the compiler will start some guess
work on what the last 8 digits would be been.

The easiest way to see this in action is copy your float into a double
and then print out this double and the original float.
 
P

Pete Becker

The following happens when you do if(i==d)
i is implicitly expanded to double size. The problem being that only
the first 8 decimals of i have a value (1.1000000 should be about
right) a double has a precision of (at least) 16 decimals so you end up
with a number 1.1000000???????? where the questionmarks can be anything
between 00000000 and 49999999 because 1.1 does not fit perfectly in the
double (or float) binary format so the compiler will start some guess
work on what the last 8 digits would be been.

NO, THE COMPILER DOES NOT GUESS WHAT THE LAST DIGITS WOULD HAVE BEEN.
Phew, sorry to shout, but this is a fundamental misconception. The
compiler generates a double that has the same value as the float. No
guessing involved; usually it's just padding with zeros. The reason the
two original values are different is that the "extra" bits in the double
value were discarded when 1.1 was stored as a float. You can't get them
back. When a float is promoted to double it usually has a different
value from a double initialized with the same initializer.
 
V

velthuijsen

Then where comes the 8 decimals of numbers come from other then taking
a wild stab in the dark and guessing number(s)?
 
H

Howard

Teddy said:
This is a precision problem
For 2 float numbers you should use '>=' or '<=' operator, not '=='
operator to judge if they equal

How are <= and >= going to tell you if the values are equal?

(And unless you happen to know what occurs when you create a float and a
double from a numeric literal, you won't even know which one you'd *expect*
to be larger or smaller than the other.)

For comparing real numbers, if you *really* need to test equality, your only
choice is to test if the two numbers are "close enough" to be considered
equal. But in general, it's better to try to avoid making such a test at
all.

-Howard
 
I

Ian Malone

(e-mail address removed) wrote:

(Context brought back; Pete Becker said:
)

Then where comes the 8 decimals of numbers come from other then taking
a wild stab in the dark and guessing number(s)?

Nowhere: the computer is using base 2, not base 10.
Binary:
..1 = 1/2
0.01 = 1/2^2
etc.

Binary Decimal
0.1 0.5
0.01 0.25
0.001 0.125
0.0001 0.0625
0.00001 0.03125
0.00011 0.09375

It can't represent 1.1 exactly in a finite number of bits; as you see
above truncating the sequence will give a series of numbers almost,
but not exactly, equal to 0.1 (decimal). The links given by others on
this thread almost certainly cover this in much more detail.
 
T

Teddy

Howard wrote
For comparing real numbers, if you *really* need to test equality,
your only choice is to test if the two numbers are "close enough"
to be considered equal.

yes, this is just what i mean
use <= or >= to test if the two numbers are close enough
 
H

Howard

Then where comes the 8 decimals of numbers come from other then taking
a wild stab in the dark and guessing number(s)?

As he said, it's probably simply padded with zeros. (And there are no
"decimals" there at all, except in the string representation for the literal
you type in and for the values printed out in your debugger or using cout.)

If I look at the memory for those in a program compiled under CodeWarrior
and running in OS X on the Mac, then here's what I see:

actual float value in hex: 0x3ff19999a0000000
actual double value in hex: 0x3ff199999999999a

float value as decimal: 1.100000023841858
double value as decimal: 1.100000000000000

You can see that the "extra" [hex] digits are set to zeros. They're not
used when the value is treated as a float, only if you later treat it as a
double. But the hardware has to store something there, because the size of
the register is big enough to hold a double, and so the compiler creates a
binary value that's as near as it can get to the desired decimal value, and
the rest of the bits are set to zero.

That decimal portion of the float "23841858" is not "randomly" picked, it's
the decimal equivalent of the binary value that gets stored, and it's that
binary value which has less precision than the double. In this case, the
hardware stores a value that is actually a little larger than the desired
value. (In some cases, it may be smaller.)

-Howard
 
R

Randy

Teddy said:
Howard wrote



yes, this is just what i mean
use <= or >= to test if the two numbers are close enough
That will not tell you if it is close. What if you had 1.1 and 15.5?
1.1 <= 15.5 = true.
now if you want to test for NEAR equal then:

fabs(x-y) < .00001

will give you an "Its close" test.
 
T

Teddy

Randy wrote
That will not tell you if it is close. What if you had
1.1 and 15.5? 1.1 <= 15.5 = true.
now if you want to test for NEAR equal then:
fabs(x-y) < .00001
will give you an "Its close" test.


You misunderstood what i said before
Of courese, it should be like this: if(fabs(f1-f2)<=1.0E-20)
I'm sorry that I didn't give an example

Nobody writes if(f1<=f2) to test if f1 and f2 are equal
It is terrible
 
P

Pete Becker

Howard said:
For comparing real numbers, if you *really* need to test equality, your only
choice is to test if the two numbers are "close enough" to be considered
equal.

If you *really* need to test equality you test equality. If you need to
test "close enough" you test "close enough." Exact equality of floating
point values is sometimes meaningful.
 
P

Pete Becker

Then where comes the 8 decimals of numbers come from other then taking
a wild stab in the dark and guessing number(s)?

I'm not completely sure what numbers you're referring to, but as a
guess, if you try to display more digits than a floating point type
holds, you'll get strange-looking results. Not because anyone is
guessing, but because binary numbers that end with all zeros don't
necessarily translate into decimal numbers that end with all zeros.
Not to mention that often values are rounded for display, so what you
see isn't necessarily what you've got.
 
H

Howard

Pete Becker said:
If you *really* need to test equality you test equality. If you need to
test "close enough" you test "close enough." Exact equality of floating
point values is sometimes meaningful.

Quite right. I probably worded that poorly. I meant that if you can't
avoid doing *some* kind of equality comparison, then comparing for "close
enough" was the only reasonable way to accomplish the task (in the general
case), because there is no guarantee that an algrabaic equality will
correspond to a physical equality (i.e., where == will return true) when
dealing with floating-point numbers on a finite-precision computer.

-Howard
 
R

Randy

You misunderstood what i said before
Of courese, it should be like this: if(fabs(f1-f2)<=1.0E-20)
I'm sorry that I didn't give an example

Nobody writes if(f1<=f2) to test if f1 and f2 are equal
It is terrible

NP! Prolly standard to assume such things I'm just picky cuz I'm "new" :)
 
P

Pete Becker

Howard said:
Quite right. I probably worded that poorly. I meant that if you can't
avoid doing *some* kind of equality comparison, then comparing for "close
enough" was the only reasonable way to accomplish the task (in the general
case), because there is no guarantee that an algrabaic equality will
correspond to a physical equality (i.e., where == will return true) when
dealing with floating-point numbers on a finite-precision computer.

Again: if equality is what you need, that's what you test for. It's well
defined, exact, and reproducible. In some cases it might be appropriate
to test for some relaxed notion of equality, but that should be by
design, not by application of some general rule. Most people apply
general rules like this one to floating point computations because they
don't understand floating point well enough to know what they're doing.
Substituting "close enough" doesn't make up for that deficiency, so it
only gives the illusion of accuracy.
 
P

Peter Julian

santosh said:
Hello,
I have two doubts on C++.
1. float i=1.1;
double d=1.1;
if(i==d)
printf("equal\n");
else
printf("not-equal\n");
what is the output?
I am getting "not-equal" as output.
Why it is so?

Thats by design. You can't compare for equality with doubles or floats. Or
rather, comparing them won't provide the expected behaviour because of the
nature of these types.
Essentially, 1.999999 and 2.0 are both valid representations of the same
number (remember the topic of significant digits?). Also, comparing doubles
in any way is an intensive CPU operation.
 

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,146
Messages
2,570,832
Members
47,374
Latest member
anuragag27

Latest Threads

Top