C++ anamaly

P

puzzlecracker

If you run this program, it gives very unexpected results. Can anyone
explain the nature of this anamaly? (also what is the function call
[and library to include linux/windows] to execute 'pause');

#include<iostream>
using namespace std;
//void pause(){ unsigned long i=0; while(i++<10000000); }

int main(){


int counter=0;
for(float i=1;i<100;i+=0.1) // pay attention
{ // pause();
std::cout<<i<<"\n";
}

cout<<endl;
return 0;


}
 
I

Ioannis Vranos

puzzlecracker said:
If you run this program, it gives very unexpected results. Can anyone
explain the nature of this anamaly? (also what is the function call
[and library to include linux/windows] to execute 'pause');

#include<iostream>
using namespace std;
//void pause(){ unsigned long i=0; while(i++<10000000); }

int main(){


int counter=0;
for(float i=1;i<100;i+=0.1) // pay attention
{ // pause();
std::cout<<i<<"\n";
}

cout<<endl;
return 0;


}


I guess the float gets printed as a double (there is no operator<<
overload for float). Use double instead.
 
P

puzzlecracker

Ioannis said:
puzzlecracker said:
If you run this program, it gives very unexpected results. Can anyone
explain the nature of this anamaly? (also what is the function call
[and library to include linux/windows] to execute 'pause');

#include<iostream>
using namespace std;
//void pause(){ unsigned long i=0; while(i++<10000000); }

int main(){


int counter=0;
for(float i=1;i<100;i+=0.1) // pay attention
{ // pause();
std::cout<<i<<"\n";
}

cout<<endl;
return 0;


}


I guess the float gets printed as a double (there is no operator<<
overload for float). Use double instead.



SAME THING - I think it has to do with the way floating point numbers
are represented.
 
J

James Aguilar

puzzlecracker said:
If you run this program, it gives very unexpected results. Can anyone
explain the nature of this anamaly? (also what is the function call
[and library to include linux/windows] to execute 'pause');

It works just fine for me on gcc 3.3.3.

Can you describe the anomaly that happens on your system?

James
 
P

puzzlecracker

what is the last number being printed in your case?

James said:
puzzlecracker said:
If you run this program, it gives very unexpected results. Can anyone
explain the nature of this anamaly? (also what is the function call
[and library to include linux/windows] to execute 'pause');

It works just fine for me on gcc 3.3.3.

Can you describe the anomaly that happens on your system?

James
 
G

Gianni Mariani

puzzlecracker said:
If you run this program, it gives very unexpected results.

What do you think is unexpected about it ?

Can anyone
explain the nature of this anamaly?

Round off error, more than likely.

0.1 is a number that can't be represented exactly.

In binary to 23 digits it is represented as the following approximation:

0.00011001100110011001100

Which is 1 10 millionth (approx) in error or more accurately.
1/10485760

When you multiply that error by 1000 you get an error of:
25/262144

i.e. 1 in 100,000 (approx).


(also what is the function call
[and library to include linux/windows] to execute 'pause');

What is pause ? Why do you need it ?
 
P

puzzlecracker

Gianni said:
puzzlecracker said:
If you run this program, it gives very unexpected results.

What do you think is unexpected about it ?

Can anyone
explain the nature of this anamaly?

Round off error, more than likely.

0.1 is a number that can't be represented exactly.

In binary to 23 digits it is represented as the following approximation:

0.00011001100110011001100

Which is 1 10 millionth (approx) in error or more accurately.
1/10485760

When you multiply that error by 1000 you get an error of:
25/262144

i.e. 1 in 100,000 (approx).


(also what is the function call
[and library to include linux/windows] to execute 'pause');

What is pause ? Why do you need it ?

how to correct this problem?
 
G

Gianni Mariani

puzzlecracker said:
Gianni Mariani wrote: .... ....

how to correct this problem?

Change the order of operations to minimize the round-off error
accumulation and/or use higher precision (double) numbers.

You can use exact numbers as well - like a quotient type.

This is one example I whipped up to come up with that bit pattern...


template <typename w_T>
w_T gcd( w_T i_v1, w_T i_v2 )
{
w_T l_vl;
w_T l_vs;
if ( i_v1 > i_v2 )
{
l_vl = i_v1;
l_vs = i_v2;
}
else
{
l_vl = i_v2;
l_vs = i_v1;
}

w_T l_t;
w_T l_t2;

do {

l_t2 = l_vl % l_vs;

l_t = l_vl;
l_vl = l_vs;
l_vs = l_t2;
} while( l_t2 );

return l_vl;
}


struct quotient
{
typedef unsigned long long t_type;

bool m_sign;
t_type m_numerator;
t_type m_denominator;

quotient(
bool i_sign,
t_type i_numerator,
t_type i_denominator
)
: m_sign( i_sign ),
m_numerator( i_numerator ),
m_denominator( i_denominator )
{
Simplify();
}

void Simplify()
{
t_type l_gcd = gcd( m_numerator, m_denominator );

if ( l_gcd != 1 )
{
m_numerator /= l_gcd;
m_denominator /= l_gcd;
}
}

quotient operator-() const
{
return quotient( !m_sign, m_numerator, m_denominator );
}

};

quotient operator+( const quotient & i_lhs, const quotient & i_rhs )
{
quotient::t_type l_demgcd = gcd( i_lhs.m_denominator,
i_rhs.m_denominator );

quotient::t_type l_mul_rhs = i_lhs.m_denominator / l_demgcd;
quotient::t_type l_mul_lhs = i_rhs.m_denominator / l_demgcd;
quotient::t_type l_den = l_mul_lhs * i_lhs.m_denominator;

if ( i_lhs.m_sign == i_rhs.m_sign )
{
return quotient(
i_lhs.m_sign,
i_lhs.m_numerator * l_mul_lhs + i_rhs.m_numerator * l_mul_rhs,
l_den
);
}
else
{
quotient::t_type l_num_lhs = i_lhs.m_numerator * l_mul_lhs;
quotient::t_type l_num_rhs = i_rhs.m_numerator * l_mul_rhs;

if ( l_num_lhs > l_num_rhs )
{
return quotient(
i_lhs.m_sign,
l_num_lhs - l_num_rhs,
l_den
);
}
else
{
return quotient(
i_rhs.m_sign,
l_num_rhs - l_num_lhs,
l_den
);
}
}

}

quotient operator-( const quotient & i_lhs, const quotient & i_rhs )
{
return i_lhs + - i_rhs;
}

quotient operator*( const quotient & i_lhs, const quotient & i_rhs )
{
return quotient(
i_rhs.m_sign != i_rhs.m_sign,
i_lhs.m_numerator * i_rhs.m_numerator,
i_lhs.m_denominator * i_rhs.m_denominator
);
}

quotient operator/( const quotient & i_lhs, const quotient & i_rhs )
{
return quotient(
i_rhs.m_sign != i_rhs.m_sign,
i_lhs.m_numerator * i_rhs.m_denominator,
i_lhs.m_denominator * i_rhs.m_numerator
);
}

template<
typename i_char_type,
class i_traitsbasic_ostream<i_char_type, i_traits>& operator << (
basic_ostream<i_char_type, i_traits> & i_ostream,
const quotient & i_value
) {

if ( i_value.m_sign )
{
i_ostream << '-';
}

i_ostream << i_value.m_numerator;

if ( i_value.m_denominator != 1 )
{
i_ostream << '/' << i_value.m_denominator;
}

return i_ostream;
}

//////////////////// example of you to use quotient this //////////////

int main()
{
quotient m_value( false, 1, 10 ); // 1/10th or 0.1

quotient m_bit( false, 1, 2 ); // 1/2 or 0,5 - the first bit.

for ( int i = 23; i --; )
{
quotient m_diff = m_value - m_bit;

if ( m_diff.m_sign )
{
std::cout << '0';
}
else
{
std::cout << '1';
m_value = m_diff;
}

m_bit.m_denominator <<= 1;
}

std::cout << " " << m_value << " " << quotient( false, 1000, 1 ) *
m_value;
}
 
J

James Aguilar

puzzlecracker said:
what is the last number being printed in your case?

99.999 -- the correct number, or, at least, the behavior I would expect.

As I'm sure you know, there is calculation error in all floating point
numbers -- both float, double, and long double. The extent of the error is
dependent upon the hardware, but I'm sure that your teachers have told you
the danger of comparing fps as equal. How is it different if you do 10000
ops on one?
 
M

Mike Wahler

puzzlecracker said:
If you run this program, it gives very unexpected results. Can anyone
explain the nature of this anamaly? (also what is the function call
[and library to include linux/windows] to execute 'pause');

You'll need to ask about Linux and Windows features in newsgroups
where they're topical.
#include<iostream>
using namespace std;
//void pause(){ unsigned long i=0; while(i++<10000000); }

int main(){


int counter=0;
for(float i=1;i<100;i+=0.1) // pay attention

Yes, you should pay attention:
http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.16
http://docs.sun.com/source/806-3568/ncg_goldberg.html

-Mike
 
I

Ioannis Vranos

James said:
99.999 -- the correct number, or, at least, the behavior I would expect.

As I'm sure you know, there is calculation error in all floating point
numbers -- both float, double, and long double. The extent of the error is
dependent upon the hardware, but I'm sure that your teachers have told you
the danger of comparing fps as equal. How is it different if you do 10000
ops on one?


Actually if you use double you will get perfectly rounded numbers while
with float you don't. I tried even with /fp:precise of VC++ 2005 Express
Beta which is very precise and expensive and I still got the same things
with float.

100% operator<< converts it to to double and that's why the added
garbage in the end.
 
A

Andrew Koenig

If you run this program, it gives very unexpected results.

When a program that uses floating-point arithmetic gives unexpected results,
the most common reason is that your expectations are incorrect.
 
J

James Aguilar

Ioannis Vranos said:
Actually if you use double you will get perfectly rounded numbers while
with float you don't. I tried even with /fp:precise of VC++ 2005 Express
Beta which is very precise and expensive and I still got the same things
with float.

100% operator<< converts it to to double and that's why the added garbage
in the end.

Interesting. =D

James
 
J

Jerry Coffin

James Aguilar wrote:

[ ... ]
As I'm sure you know, there is calculation error in all floating point
numbers -- both float, double, and long double.

Actually, neither you nor anybody else knows that -- some floating
point calculations can be done without errors, though I'm the first to
admit that it's neither common nor to be expected.
The extent of the error is
dependent upon the hardware, but I'm sure that your teachers have told you
the danger of comparing fps as equal. How is it different if you do 10000
ops on one?


The extent of the error depends not only on the number and type of
operations, but on the mixture of operation and the values involved.
Just for example, repeatedly adding or subtracting an extremely small
number to/from a much larger one vs. multiplying the smaller one and
the adding/subtracting the result. The first case may have no effect on
the value at all while the latter does.

Likewise, the exact values determine whether they will be rounded -- if
the original example used .125 instead of .1, no rounding would have
occurred, at least on any ordinary computer (because it's doing the
work in binary, and .125 is a power of 2 where .1 is not).

Ultimately, most problems arise because people are accustomed to
decimal while computers work in binary. We're accustomed to the fact
that 1/3 (for example) can't be expressed precisely in a finite number
of places after the decimal point.

There's a general rule here: if you start with a fraction and you want
to express it in a different number base, then one of two things will
apply: either the prime factors of the denominator of the fraction are
also divisors of the target number base, or else the fraction can't be
expressed precisely in a finite number of places in that base.

Since a computer uses binary, the number base has only one prime
factor: 2. As such, any fraction whose denominator isn't a power of 2
MUST be rounded when expressed by the computer.
 
J

Jack Klein

Actually if you use double you will get perfectly rounded numbers while
with float you don't.

Really? Guaranteed by the C++ standard?
I tried even with /fp:precise of VC++ 2005 Express
Beta which is very precise and expensive and I still got the same things
with float.

Oh, I see, we're talking about one particular compiler. What's the
relevance of that in this context?
 
I

Ioannis Vranos

Jack said:
Oh, I see, we're talking about one particular compiler. What's the
relevance of that in this context?


I checked the standard and the provided operator<< for cout (which is
basic_ostream<char>) include:


basic_ostream<charT,traits>& operator<<(bool n);
basic_ostream<charT,traits>& operator<<(short n);
basic_ostream<charT,traits>& operator<<(unsigned short n);
basic_ostream<charT,traits>& operator<<(int n);
basic_ostream<charT,traits>& operator<<(unsigned int n);
basic_ostream<charT,traits>& operator<<(long n);
basic_ostream<charT,traits>& operator<<(unsigned long n);
basic_ostream<charT,traits>& operator<<(float f);
basic_ostream<charT,traits>& operator<<(double f);
basic_ostream<charT,traits>& operator<<(long double f);



So it is indeed some floating point precision problem, which however
gets fixed:


#include <iostream>
#include <ostream>


int main()
{
using namespace std;

cout.precision(4);

for(float i=1;i<100;i+=0.1)
cout<<i<<endl;
}
 
M

msalters

Ioannis Vranos wrote:
....
So it is indeed some floating point precision problem, which however
gets fixed:

#include <iostream>
#include <ostream>

int main()
{
std::cout.precision(4);

for(float i=1;i<100;i+=0.1)
std::cout<<i<<endl;
}

Not fixed. Hidden.

Just count to 1000, or 10000. I can guarantee you there will be
a point where it fails. The reason is simple: 0.1 is not equal
to the rational number 1/10, but a binary approximation. You
only hide the accumulated error, until it's >0.0001.
Regards,
Michiel Salters
 
I

Ioannis Vranos

msalters said:
Not fixed. Hidden.

Just count to 1000, or 10000. I can guarantee you there will be
a point where it fails. The reason is simple: 0.1 is not equal
to the rational number 1/10, but a binary approximation. You
only hide the accumulated error, until it's >0.0001.


OK I can understand that. However why when we use double everything
works ok instead?


#include <iostream>
#include <ostream>


int main()
{
using namespace std;

for(double i=1; i<100; i+=0.1)
cout<<i<<endl;
}


1
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
3
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.8
3.9
4
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
5
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
5.9
6
6.1
6.2
6.3
6.4
6.5
6.6
6.7
6.8
6.9
7
7.1
7.2
7.3
7.4
7.5
7.6
7.7
7.8
7.9
8
8.1
8.2
8.3
8.4
8.5
8.6
8.7
8.8
8.9
9
9.1
9.2
9.3
9.4
9.5
9.6
9.7
9.8
9.9
10
10.1
10.2
10.3
10.4
10.5
10.6
10.7
10.8
10.9
11
11.1
11.2
11.3
11.4
11.5
11.6
11.7
11.8
11.9
12
12.1
12.2
12.3
12.4
12.5
12.6
12.7
12.8
12.9
13
13.1
13.2
13.3
13.4
13.5
13.6
13.7
13.8
13.9
14
14.1
14.2
14.3
14.4
14.5
14.6
14.7
14.8
14.9
15
15.1
15.2
15.3
15.4
15.5
15.6
15.7
15.8
15.9
16
16.1
16.2
16.3
16.4
16.5
16.6
16.7
16.8
16.9
17
17.1
17.2
17.3
17.4
17.5
17.6
17.7
17.8
17.9
18
18.1
18.2
18.3
18.4
18.5
18.6
18.7
18.8
18.9
19
19.1
19.2
19.3
19.4
19.5
19.6
19.7
19.8
19.9
20
20.1
20.2
20.3
20.4
20.5
20.6
20.7
20.8
20.9
21
21.1
21.2
21.3
21.4
21.5
21.6
21.7
21.8
21.9
22
22.1
22.2
22.3
22.4
22.5
22.6
22.7
22.8
22.9
23
23.1
23.2
23.3
23.4
23.5
23.6
23.7
23.8
23.9
24
24.1
24.2
24.3
24.4
24.5
24.6
24.7
24.8
24.9
25
25.1
25.2
25.3
25.4
25.5
25.6
25.7
25.8
25.9
26
26.1
26.2
26.3
26.4
26.5
26.6
26.7
26.8
26.9
27
27.1
27.2
27.3
27.4
27.5
27.6
27.7
27.8
27.9
28
28.1
28.2
28.3
28.4
28.5
28.6
28.7
28.8
28.9
29
29.1
29.2
29.3
29.4
29.5
29.6
29.7
29.8
29.9
30
30.1
30.2
30.3
30.4
30.5
30.6
30.7
30.8
30.9
31
31.1
31.2
31.3
31.4
31.5
31.6
31.7
31.8
31.9
32
32.1
32.2
32.3
32.4
32.5
32.6
32.7
32.8
32.9
33
33.1
33.2
33.3
33.4
33.5
33.6
33.7
33.8
33.9
34
34.1
34.2
34.3
34.4
34.5
34.6
34.7
34.8
34.9
35
35.1
35.2
35.3
35.4
35.5
35.6
35.7
35.8
35.9
36
36.1
36.2
36.3
36.4
36.5
36.6
36.7
36.8
36.9
37
37.1
37.2
37.3
37.4
37.5
37.6
37.7
37.8
37.9
38
38.1
38.2
38.3
38.4
38.5
38.6
38.7
38.8
38.9
39
39.1
39.2
39.3
39.4
39.5
39.6
39.7
39.8
39.9
40
40.1
40.2
40.3
40.4
40.5
40.6
40.7
40.8
40.9
41
41.1
41.2
41.3
41.4
41.5
41.6
41.7
41.8
41.9
42
42.1
42.2
42.3
42.4
42.5
42.6
42.7
42.8
42.9
43
43.1
43.2
43.3
43.4
43.5
43.6
43.7
43.8
43.9
44
44.1
44.2
44.3
44.4
44.5
44.6
44.7
44.8
44.9
45
45.1
45.2
45.3
45.4
45.5
45.6
45.7
45.8
45.9
46
46.1
46.2
46.3
46.4
46.5
46.6
46.7
46.8
46.9
47
47.1
47.2
47.3
47.4
47.5
47.6
47.7
47.8
47.9
48
48.1
48.2
48.3
48.4
48.5
48.6
48.7
48.8
48.9
49
49.1
49.2
49.3
49.4
49.5
49.6
49.7
49.8
49.9
50
50.1
50.2
50.3
50.4
50.5
50.6
50.7
50.8
50.9
51
51.1
51.2
51.3
51.4
51.5
51.6
51.7
51.8
51.9
52
52.1
52.2
52.3
52.4
52.5
52.6
52.7
52.8
52.9
53
53.1
53.2
53.3
53.4
53.5
53.6
53.7
53.8
53.9
54
54.1
54.2
54.3
54.4
54.5
54.6
54.7
54.8
54.9
55
55.1
55.2
55.3
55.4
55.5
55.6
55.7
55.8
55.9
56
56.1
56.2
56.3
56.4
56.5
56.6
56.7
56.8
56.9
57
57.1
57.2
57.3
57.4
57.5
57.6
57.7
57.8
57.9
58
58.1
58.2
58.3
58.4
58.5
58.6
58.7
58.8
58.9
59
59.1
59.2
59.3
59.4
59.5
59.6
59.7
59.8
59.9
60
60.1
60.2
60.3
60.4
60.5
60.6
60.7
60.8
60.9
61
61.1
61.2
61.3
61.4
61.5
61.6
61.7
61.8
61.9
62
62.1
62.2
62.3
62.4
62.5
62.6
62.7
62.8
62.9
63
63.1
63.2
63.3
63.4
63.5
63.6
63.7
63.8
63.9
64
64.1
64.2
64.3
64.4
64.5
64.6
64.7
64.8
64.9
65
65.1
65.2
65.3
65.4
65.5
65.6
65.7
65.8
65.9
66
66.1
66.2
66.3
66.4
66.5
66.6
66.7
66.8
66.9
67
67.1
67.2
67.3
67.4
67.5
67.6
67.7
67.8
67.9
68
68.1
68.2
68.3
68.4
68.5
68.6
68.7
68.8
68.9
69
69.1
69.2
69.3
69.4
69.5
69.6
69.7
69.8
69.9
70
70.1
70.2
70.3
70.4
70.5
70.6
70.7
70.8
70.9
71
71.1
71.2
71.3
71.4
71.5
71.6
71.7
71.8
71.9
72
72.1
72.2
72.3
72.4
72.5
72.6
72.7
72.8
72.9
73
73.1
73.2
73.3
73.4
73.5
73.6
73.7
73.8
73.9
74
74.1
74.2
74.3
74.4
74.5
74.6
74.7
74.8
74.9
75
75.1
75.2
75.3
75.4
75.5
75.6
75.7
75.8
75.9
76
76.1
76.2
76.3
76.4
76.5
76.6
76.7
76.8
76.9
77
77.1
77.2
77.3
77.4
77.5
77.6
77.7
77.8
77.9
78
78.1
78.2
78.3
78.4
78.5
78.6
78.7
78.8
78.9
79
79.1
79.2
79.3
79.4
79.5
79.6
79.7
79.8
79.9
80
80.1
80.2
80.3
80.4
80.5
80.6
80.7
80.8
80.9
81
81.1
81.2
81.3
81.4
81.5
81.6
81.7
81.8
81.9
82
82.1
82.2
82.3
82.4
82.5
82.6
82.7
82.8
82.9
83
83.1
83.2
83.3
83.4
83.5
83.6
83.7
83.8
83.9
84
84.1
84.2
84.3
84.4
84.5
84.6
84.7
84.8
84.9
85
85.1
85.2
85.3
85.4
85.5
85.6
85.7
85.8
85.9
86
86.1
86.2
86.3
86.4
86.5
86.6
86.7
86.8
86.9
87
87.1
87.2
87.3
87.4
87.5
87.6
87.7
87.8
87.9
88
88.1
88.2
88.3
88.4
88.5
88.6
88.7
88.8
88.9
89
89.1
89.2
89.3
89.4
89.5
89.6
89.7
89.8
89.9
90
90.1
90.2
90.3
90.4
90.5
90.6
90.7
90.8
90.9
91
91.1
91.2
91.3
91.4
91.5
91.6
91.7
91.8
91.9
92
92.1
92.2
92.3
92.4
92.5
92.6
92.7
92.8
92.9
93
93.1
93.2
93.3
93.4
93.5
93.6
93.7
93.8
93.9
94
94.1
94.2
94.3
94.4
94.5
94.6
94.7
94.8
94.9
95
95.1
95.2
95.3
95.4
95.5
95.6
95.7
95.8
95.9
96
96.1
96.2
96.3
96.4
96.5
96.6
96.7
96.8
96.9
97
97.1
97.2
97.3
97.4
97.5
97.6
97.7
97.8
97.9
98
98.1
98.2
98.3
98.4
98.5
98.6
98.7
98.8
98.9
99
99.1
99.2
99.3
99.4
99.5
99.6
99.7
99.8
99.9
100
 
M

Mike Wahler

Ioannis Vranos said:
OK I can understand that. However why when we use double everything
works ok instead?


#include <iostream>
#include <ostream>


int main()
{
using namespace std;

for(double i=1; i<100; i+=0.1)

Increase the value 100 significantly (e.g. to INT_MAX),
and you'll likely (but not necessarily) see a difference.
With only 100 iterations, the error has not accumulated
sufficiently to be apparent with your code.
cout<<i<<endl;

Another way to show the problem (even with a smaller
number of iterations) is to increase the output precision,
e.g.:

cout << fixed << setprecision(15) << '\n';

I.e. the call to operator<< is outputting a rounded
value, not necessarily the exact value of 'i'.

E.g. The following program:

#include <ios>
#include <iomanip>
#include <iostream>

int main()
{

std::cout << std::fixed
<< std::setprecision(15);

for(double i=0; i < 10; i += 0.1)
std::cout << i << '\n';

return 0;
}

.... when built with VC++ and executed on an Intel
Pentium, gives the output of:

0.000000000000000
0.100000000000000
0.200000000000000
0.300000000000000
0.400000000000000
0.500000000000000
0.600000000000000
0.700000000000000
0.800000000000000
0.900000000000000
1.000000000000000
1.100000000000000
1.200000000000000
1.300000000000000
1.400000000000000
1.500000000000000
1.600000000000000
1.700000000000000
1.800000000000001
1.900000000000001
2.000000000000000
2.100000000000001
2.200000000000001
2.300000000000001
2.400000000000001
2.500000000000001
2.600000000000001
2.700000000000001
2.800000000000001
2.900000000000001
3.000000000000001
3.100000000000001
3.200000000000002
3.300000000000002
3.400000000000002
3.500000000000002
3.600000000000002
3.700000000000002
3.800000000000002
3.900000000000002
4.000000000000002
4.100000000000001
4.200000000000001
4.300000000000001
4.400000000000000
4.500000000000000
4.600000000000000
4.699999999999999
4.799999999999999
4.899999999999999
4.999999999999998
5.099999999999998
5.199999999999998
5.299999999999997
5.399999999999997
5.499999999999996
5.599999999999996
5.699999999999996
5.799999999999995
5.899999999999995
5.999999999999995
6.099999999999994
6.199999999999994
6.299999999999994
6.399999999999993
6.499999999999993
6.599999999999993
6.699999999999992
6.799999999999992
6.899999999999992
6.999999999999991
7.099999999999991
7.199999999999990
7.299999999999990
7.399999999999990
7.499999999999989
7.599999999999989
7.699999999999989
7.799999999999988
7.899999999999988
7.999999999999988
8.099999999999987
8.199999999999987
8.299999999999987
8.399999999999986
8.499999999999986
8.599999999999985
8.699999999999985
8.799999999999985
8.899999999999984
8.999999999999984
9.099999999999984
9.199999999999983
9.299999999999983
9.399999999999983
9.499999999999982
9.599999999999982
9.699999999999982
9.799999999999981
9.899999999999981
9.999999999999981

If you increment 'i' by 0.1 enough times, the error
will eventually work its way toward the more significant
digits and show up even with 'cout's default precision.

Again, don't depend upon the result from 'cout' to
tell you the exact value of a floating point object
An implementation could even have more significant
digits than 15. (check your <limits> header for
your implementation limits.)

It's simply not possible to represent every decimal
floating point value in binary. Behavior of output
functions cannot change this fact.


-Mike
 

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,201
Messages
2,571,048
Members
47,647
Latest member
NelleMacy9

Latest Threads

Top