两个迭代器初始化容器出现浮点数舍入

Recently, while organizing my notes, I discovered a strange issue:


The output of this code is:

0.1 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9 10
0 1 2 3 4 5 6 7 8 9

The code is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vector<double> testDouble;
for(double i=0.1;i<=10;i+=1.1){
testDouble.push_back(i);
}
// Traverse and output testDouble
for(vector<double>::iterator testiter=testDouble.begin();
testiter!=testDouble.end();testiter++)
cout<<*testiter<<" ";
cout<<endl;
// Initialize testint as a copy of testDouble (type conversion)
vector<int> testint(testDouble.begin(),testDouble.end());
// Traverse and output testint
for(vector<int>::iterator testintiter=testint.begin();
testintiter!=testint.end();testintiter++){
cout<<*testintiter<<" ";
}

Why does the last pair of outputs show “10, 9”?

At first, I thought it was just an issue of converting double to int, and then tested:

1
2
3
4
vector<double> test;
test.push_back(8.9 + 1.1);
vector<int> testint(test.begin(), test.end());
cout<<*testint.begin()<<endl;

The output was:

From the result, it seems it’s not just a conversion issue.

Now, we can infer from the latter results:
The element value 8.9 output earlier is not equal to the floating-point constant 8.9

After checking a lot of materials, I found out the root of the problem:

Precision issue, the floating-point numbers in computers are not in decimal form, so it’s not possible to precisely add up to 10; the number is approximately 9.99999999999998 (it can output 10 due to floating-point rounding(IEEE 754)), and then when converted to int, it becomes 9 (truncated), which has nothing to do with the container or iterators.

Floating-point rounding (excerpted from Wikipedia IEEE 754):

  • Round to nearest: Round to the nearest value, with ties to even (Ties To Even, this is the default rounding method): it will round the result to the nearest representable value, but when two numbers are equally close, it takes the even one (which ends in 0 in binary).
  • Round towards +∞: it will round the result towards positive infinity.
  • Round towards -∞: it will round the result towards negative infinity.
  • Round towards 0: it will round the result towards 0.

Solution: Converting double to (forced conversion) int is truncation, and you can use the round function to round the values of type double

double round(double);

Testing the value assignment with round conversion (rounded up)

Let’s also test test.end()-1 and round(test.end()-1)

Conclusion: When encountering the need for forced data type conversion, you should pay close attention to the storage and computation methods of that type, and also take some time to review the IEEE standards.

The article is finished. If you have any questions, please comment and communicate.

Scan the QR code on WeChat and follow me.

Title:两个迭代器初始化容器出现浮点数舍入
Author:LIPENGZHA
Publish Date:2015/08/18 12:39
World Count:1.6k Words
Link:https://en.imzlp.com/posts/15409/
License: CC BY-NC-SA 4.0
Reprinting of the full article is prohibited.
Your donation will encourage me to keep creating!