-1

I'm currently facing a problem but I don't know why it wrong?

// ll ís long long

ll cnt = 24822089714520516;

cout << "xpow: " << xpow(10LL, 16) << endl;
cout << "cnt: " << cnt << endl;

ll a = xpow(10LL, 16) + cnt - 1;
ll b = round(xpow(10LL, 16)) + cnt - 1;

cout << "cur_num (without round): " << a << endl;
cout << "cur_num (with round): " << b << endl;

with xpow is defined by myself:

ll xpow(ll a, ll b) {
  ll ans = 1;
  while (b) {
    if (b & 1)
      ans *= a;
    b >>= 1;
    if (b)
      a *= a;
  };
  return ans;
};

When I run my code, I get this log:

xpow: 10000000000000000
cnt: 24822089714520516
cur_num (without round): 34822089714520515
cur_num (with round): 34822089714520516

As you see, my result if I use round is differenced with one when I don't round (smaller than 1 unit)

It may be my computer's problem, but may be no. Can anyone explain why?

Thanks so much!

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • 2
    [`round()`](https://en.cppreference.com/w/cpp/numeric/math/round) is to dealing with floating-point values. They may not have enough precision to handle such large value precisely. – MikeCAT Jun 16 '21 at 15:59
  • 3
    Use `int64_t`, not `long long` or the horrible macro `ll`. – PaulMcKenzie Jun 16 '21 at 16:02
  • 1
    Please don't use aliases (or even worse, macros) for standard types. Those makes the code much harder to read and understand (and therefore maintain). Such aliases are typically show-cased on so-called "competition" sites which are only good for showing really bad programming habits. – Some programmer dude Jun 16 '21 at 16:03
  • That right, I also think it is a bad programming habits. But this code is a piece of my code in my last competitive contest :V – Trần Gia Bảo Jun 16 '21 at 16:09
  • Ye, I know it. Because before using xpow (is defined by myself), I used pow (builtin function) so I must use round to prevent floating-point problem. After that I tried to define xpow, and randomly run my code while coding, I get this problem. So I tried to find a solution, and post here ... – Trần Gia Bảo Jun 16 '21 at 16:16

1 Answers1

2

In many C++ implementations, the long long type is 64 bits long, and the double type is 64 bits long. When this happens, a variable of type double cannot exactly represent all possible long long values, and in particular large long long values might be approximated incorrectly by a double.

Here, round converts your long long to a double, introducing some imprecision.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065