ฉันลองใช้ตัวอย่างที่รุนแรงในคำตอบที่ Steve Jessop ให้มา
#include <iostream>
#include <iomanip>
#include <cmath>
int main()
{
    long billion = 1000000000;
    double big = 1.0;
    double small = 1e-9;
    double expected = 2.0;
    double sum = big;
    for (long i = 0; i < billion; ++i)
        sum += small;
    std::cout << std::scientific << std::setprecision(1) << big << " + " << billion << " * " << small << " = " <<
        std::fixed << std::setprecision(15) << sum <<
        "    (difference = " << std::fabs(expected - sum) << ")" << std::endl;
    sum = 0;
    for (long i = 0; i < billion; ++i)
        sum += small;
    sum += big;
    std::cout  << std::scientific << std::setprecision(1) << billion << " * " << small << " + " << big << " = " <<
        std::fixed << std::setprecision(15) << sum <<
        "    (difference = " << std::fabs(expected - sum) << ")" << std::endl;
    return 0;
}
ฉันได้ผลลัพธ์ดังต่อไปนี้:
1.0e+00 + 1000000000 * 1.0e-09 = 2.000000082740371    (difference = 0.000000082740371)
1000000000 * 1.0e-09 + 1.0e+00 = 1.999999992539933    (difference = 0.000000007460067)
ข้อผิดพลาดในบรรทัดแรกจะใหญ่กว่าในบรรทัดที่สองสิบเท่า
หากฉันเปลี่ยนdoubles เป็นfloats ในโค้ดด้านบนฉันจะได้รับ:
1.0e+00 + 1000000000 * 1.0e-09 = 1.000000000000000    (difference = 1.000000000000000)
1000000000 * 1.0e-09 + 1.0e+00 = 1.031250000000000    (difference = 0.968750000000000)
ไม่มีคำตอบใดที่ใกล้เคียงกับ 2.0 (แต่ข้อที่สองใกล้กว่าเล็กน้อย)
การใช้การสรุป Kahan (พร้อมdoubles) ตามที่ Daniel Pryden อธิบายไว้:
#include <iostream>
#include <iomanip>
#include <cmath>
int main()
{
    long billion = 1000000000;
    double big = 1.0;
    double small = 1e-9;
    double expected = 2.0;
    double sum = big;
    double c = 0.0;
    for (long i = 0; i < billion; ++i) {
        double y = small - c;
        double t = sum + y;
        c = (t - sum) - y;
        sum = t;
    }
    std::cout << "Kahan sum  = " << std::fixed << std::setprecision(15) << sum <<
        "    (difference = " << std::fabs(expected - sum) << ")" << std::endl;
    return 0;
}
ฉันได้รับ 2.0:
Kahan sum  = 2.000000000000000    (difference = 0.000000000000000)
และแม้ว่าฉันจะเปลี่ยนdoubles เป็นfloats ในโค้ดด้านบนฉันจะได้รับ:
Kahan sum  = 2.000000000000000    (difference = 0.000000000000000)
ดูเหมือนว่า Kahan จะเป็นหนทางไป!