1

I am talking about converting floats that already store integer values (like 10.0) I need to do this because I want to create a simple function that reverses a given integer, and it uses a line of code that looks something like this: ans += x % (int)pow(10, i); (the % operator needs both arguments to be integer, and pow returns a double)

C++ is not very happy doing this conversion properly. For pow(10, 4), I get a value of 9999, which is very irritating. Why this error occurs is obvious, 10^4 must have been stored as 9999.999999... or something like that. I could possibly fix this error by using the lround() function, but that would be a less than optimal solution because what if I overlook a similar error like this?

Is there a way to do mathematics in C++ without worrying about such trivialties? If not, what language should I choose to do computation like this? I have briefly used the bigInt library in python. Any suggestions regarding which language and library to use to tackle this issue would be very helpful.

Andre Kampling
  • 5,476
  • 2
  • 20
  • 47
Aayush Mahajan
  • 3,856
  • 6
  • 25
  • 32
  • 1
    `lround` seems to be exactly what you need - why do you say that it's "less than optimal"? – Oliver Charlesworth Jun 12 '17 at 12:22
  • "10^4 must have been stored as 9999.999999" Read up the IEEE754 standard, it covers how float numbers are stored to memory – R. Joiny Jun 12 '17 at 12:23
  • 2
    Have a read of : https://stackoverflow.com/questions/588004/is-floating-point-math-broken – Richard Critten Jun 12 '17 at 12:24
  • @OliverCharlesworth I don't want to deal with implementation complexity that C++ poses. When the code didn't work, I assumed that there was a problem with the logic, and wasted quite some time figuring what went wrong. My purpose is purely academic, so C++ offers no real advantage to me in terms of speed. I just wanted to hear from people what libraries/language/techniques they use when they want to focus completely on algorithms and not worry about if the language would offer hurdles. – Aayush Mahajan Jun 12 '17 at 12:27
  • 2
    When it comes to floating-point precision, you'd get similar issues in most other languages. – Oliver Charlesworth Jun 12 '17 at 12:28
  • 2
    @AayushMahajan Binary floating point number numbers can not accurately represent Decimal floating point numbers in the vast majority of cases. So you have 3 choices: (1) abandon floating point and use multi-precision integer arithmetic, (2) learn what binary floating point is and determinate if it meets your needs or (3) use a 3rd party multi-precision (big-number) library, – Richard Critten Jun 12 '17 at 12:32
  • So you want a language that lets you focus completely on the problem with no overhead from learning the language or working around its quirks. That is inherently impossible. – nwp Jun 12 '17 at 12:35
  • If you apply this operation very often, then it would be better to pre-compute an (long) integer array `powof10` so that `powof10[k]` is exactly `10^k` by just iterating `powof10[k+1]=10*powof10[k] `. – Lutz Lehmann Jun 12 '17 at 12:59
  • 1
    *"What if I overlook a similar error like this?"* How could you overlook it? You had to insert an explicit cast to `int`, so just train yourself to round instead of cast. It won't be any slower. That simple-looking cast is not free. – Cody Gray - on strike Jun 12 '17 at 13:00
  • *"Is there a way to do mathematics in C++ without worrying about such trivialities?"* Choosing the right data types for your application is **not** a triviality; in fact, it's probably the *most* important decision you make as a programmer. If you need decimal values to be exact (infinitely precise), floating point numbers are the wrong choice for that. If they don't need to be *exact*, but merely *close enough*, then `lround` seems like the way to do that. – trent Jun 12 '17 at 14:42
  • (Although beware of large numbers, too -- `pow(3, 34)` will never round correctly because `double` can't represent 16677181699666569 to within an accuracy of 1.0.) – trent Jun 12 '17 at 14:54

1 Answers1

2

In other languages you have types for doing accurate math operations like in C# you have the decimal and in Java the BigDecimal type for example. So that problems like this:

printf (" %.20f \n", 3.6);
--> 3.60000000000000008882

or

0.1 + 0.2
--> 0.30000000000000004

does not happen.

In C++ you can use for example: The GNU Multiple Precision arithmetic library or Boost.Multiprecision or DecimalForCPP (header only). Surely there are more libraries available.

If you use such types, remember that they are slower than the inaccurate floating point types. But if you work with money for example, it's a must!

Andre Kampling
  • 5,476
  • 2
  • 20
  • 47