-1

I need truncation of 2 decimal digits after decimal comma. I am using following code in C++:

auto doubleTmp = value * 100.00;
int64_t tmp = static_cast<int64_t>(doubleTmp);
double res = ( static_cast<double>(tmp) ) /100.00;

but for example when I set value = 70.82 doubleTmp is 70.8199999 and result is 70.81. What will better way for this and why?

Vladimir Yanakiev
  • 1,240
  • 1
  • 16
  • 25
  • You are trying to round to a value that simply does not exist! Why not apply precision limits at the point of use, e.g. output to console? What is the use? What is the goal? – Lightness Races in Orbit Jan 02 '19 at 13:58
  • 4
    1) Related: [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) 2) Sidenote: How can you multiply `70.82` by `100.00`, and get `70.8199999` as a result? O.o – Algirdas Preidžius Jan 02 '19 at 13:59
  • 1
    Are you storing money? If so you shouldn't use a floating point type and use an integer representing the number of cents you have. If this isn't the case, do you really need to round or just display to decimal places? If that is the case just tell the output stream to show 2 places. – NathanOliver Jan 02 '19 at 13:59
  • 3
    And your rounding is truncation, not rounding, use `std::lround`. – Matthieu Brucher Jan 02 '19 at 14:00

1 Answers1

2

The problem is that neither the input value nor the result res is representable in a computer memory accurately for 70.82. As @MatthieuBrucher suggested, you should use std::lround; consider the following code:

auto value = 70.82;
std::cout << std::fixed << std::setprecision(20) << value << std::endl;

auto tmp = std::lround(value * 100.0);
std::cout << tmp << std::endl;

double res = static_cast<double>(tmp) / 100.00;
std::cout << std::fixed << std::setprecision(20) << res << std::endl;

Which gives the following output:

70.81999999999999317879
7082
70.81999999999999317879

However, you can store the result as a pair of integral numbers, where the first one will represent the integral part and the second one the fractional part:

auto res_integral = tmp / 100;
auto res_fractional = tmp % 100;
std::cout << res_integral << "." << res_fractional << std::endl;

Or, simply store it as tmp with the knowledge that you are storing 100*x instead of x.

Daniel Langr
  • 22,196
  • 3
  • 50
  • 93