简体   繁体   中英

C++ Addition Not Working

I wrote up a solution for a Google Code Jam problem as demonstrated:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <cmath>

using namespace std;

int main(int argc, char** argv) {
        ifstream in;
        in.open(argv[1]);
        int t, c = 0;
        in >> t;
        while(c++<t) {
                string msg;
                in >> msg;
                map<char,int> m;
                int base = 0;
                for(char& ch : msg) {
                        if(!m[ch]) {
                                base++;
                                m[ch] = base == 1 ? base : (base == 2 ? -1 : base - 1);
                        }
                }
                if(base < 2)
                        base = 2;
                double total = 0;
                double p = pow(base, msg.size()-1);
                for(char& ch : msg) {
                        if(m[ch] != -1) {
                                if(c == 37) cout << "total=" << total << "+" << (m[ch] * p) << "=" << total + (m[ch] * p) << endl;
                                total = total + (m[ch] * p);
                        }
                        p /= base;
                }
                cout.precision(0);
                cout << fixed << "Case #" << c << ": " << total << endl;
        }
        in.close();
        return 0;
}

As you can see I have some debug statements being printed out for case 37 because some weird stuff happen there:

Case #36: 1000000000000000000
total=0+450283905890997376=450283905890997376
total=450283905890997376+100063090197999424=550346996088996800
total=550346996088996800+16677181699666570=567024177788663360
total=567024177788663360+5559060566555523=572583238355218880
total=572583238355218880+1853020188851841=574436258544070720
total=574436258544070720+1235346792567894=575671605336638592
total=575671605336638592+205891132094649=575877496468733248
total=575877496468733248+68630377364883=575946126846098112
total=575946126846098112+22876792454961=575969003638553088
total=575969003638553088+15251194969974=575984254833523072
total=575984254833523072+847288609443=575985102122132544
total=575985102122132544+564859072962=575985666981205504
total=575985666981205504+62762119218=575985729743324736
total=575985729743324736+20920706406=575985750664031168
total=575985750664031168+6973568802=575985757637600000
total=575985757637600000+129140163=575985757766740160
total=575985757766740160+28697814=575985757795437952
total=575985757795437952+1594323=575985757797032256
total=575985757797032256+177147=575985757797209408
total=575985757797209408+59049=575985757797268480
total=575985757797268480+6561=575985757797275072
total=575985757797275072+4374=575985757797279424
total=575985757797279424+729=575985757797280128
total=575985757797280128+81=575985757797280192
total=575985757797280192+2=575985757797280192
Case #37: 575985757797280192

As you can see, at some point the addition just works incorrectly (eg 575985757797279424+729 = 575985757797280153 not 575985757797280128)

I'm incredibly dumbfounded by this behavior and would greatly appreciate any possible explanation.

You've reached the limits of precision for your chosen floating-point type.

If you insist on avoiding integers (ie fixed point), you'll need an arbitrary-precision numerical library to best it. You should also read The Floating-Point Guide before continuing to use these features.

However, the figures you have here would all fit into a 64-bit integer. Why not just use that and save yourself some trouble?

Double has 3 components sign,exponent,fraction. For example 1.2345 is represented as 12345*10power-4

Even though Double has size as long long it has some bits dedicated for exponent part so the precision is less than that of long long which gives float an accuracy of 7 decimal digits and double an accuracy of 16 decimal digits.Since floating point arithmetic are not precise after specified number of digits

Also read
1. https://chortle.ccsu.edu/java5/Notes/chap11/ch11_2.html
2. http://codeforces.com/blog/entry/1521?#comment-28329 (about pow in c++)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM