0

In my below program,

main
{
  // value is 476 
  int value = 476;

  // here dimension shows as 0.100000001
  float dimension = 0.1f;



 /// Here I am expecting value as 47.6,
 /// But it gives value as 47.600002288818......
 double result = value * dimension;
}

I want to save the value directly in database, So is there any inbuild function to get the expected value ?

Expected : 47.6 instead of 47.600002288.....

Aneesh Narayanan
  • 3,220
  • 11
  • 31
  • 48
  • 4
    In case you are wondering why this is happening: [Is floating point math broken?](http://stackoverflow.com/q/588004/669576). – 001 Dec 30 '16 at 13:57
  • 3
    The value `47.6` does not exist in any binary floating point type, you can only get approximations. What's your database type? –  Dec 30 '16 at 13:58
  • Learn about how floating point numbers are stored in memory as every programmer should. – DeiDei Dec 30 '16 at 14:00
  • 5
    [What Every Programmer Should Know About Floating-Point Arithmetic](http://floating-point-gui.de/) – Angew is no longer proud of SO Dec 30 '16 at 14:01
  • You omitted the details of how you actually formatted the value: when done correctly, it should print a decent value. However, with the given code it is unlikely that a decent value is actually computed: you'd probably have better luck using `double dimension(10); double result(value / dimension);`. – Dietmar Kühl Dec 30 '16 at 14:08
  • Yes I understood. But I am looking for a code snippet/ function to get the result as 47.6 only – Aneesh Narayanan Dec 30 '16 at 14:15
  • 2
    @AneeshNarayanan Then you plainly *don't* understand. It's impossible to get the exact value 47.6 in a `double` on your system. –  Dec 30 '16 at 14:22
  • Or is there any way to set precision ? – Aneesh Narayanan Dec 30 '16 at 14:37
  • *Please* read this: [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) - all of it (twice). – Jesper Juhl Dec 30 '16 at 16:27

3 Answers3

3

There are a few ways, but in all cases you will have to figure out and decide how many digits of precision your floating point values should represent. There's nothing about a float that says "I'm actually .1 instead of 0.100000001".

Once you decided on, say, that your values should carry two digits of precision, there are a few ways to round them off. One simple way is to use stream formatting:

#include <sstream>
#include <iomanip>

std::ostringstream o;

    o << std::setiosflags(std::ios::fixed) << std::setprecision(2) << 0.1;

std::string s=o.str();

You will now find "0.10" in s.

If you do not know how many digits of precisions are significant as a result of whatever calculations you're doing, your only option is to use a dedicated library for fixed precision arithmetic, like GMP.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
0

Floating point is, in practice, has a mantissa represented in binary (base 2). One consequence of this is that 0.1 decimal (aka the fraction 1/10) cannot be exactly represented in floating point.

The reason is the same as 1/3 cannot be represented exactly in a fixed number of decimal places - it is an infinitely recurring value 0.3333333....., and truncating it to a finite number of places introduces an error. The only difference is that 1/10 is a infinitely recurring value in base 2. So it cannot be represented exactly in a finite number of binary digits.

There are obviously other values affected in such a way (such as 0.2, 0.6, etc). Such errors are an inherent property of floating point representations .... or, to put it another way, floating point represents an approximation (the value with a potential lack of precision). And, when doing a sequence of calculations, the errors in the values propagate.

Since there is no way to exactly represent the value 0.1 in floating point (and other values), there is no way to exactly store a floating point value into a database and get a value that is exactly 0.1.

You can try printing the value in a way that limits the precision of output, such as

#include <sstream>
#include <iomanip>
#include <string>

std::ostringstream o;

o << std::fixed << std::setprecision(2) << result;

std::string s=o.str();

Bear in mind this controls how result is formatted (e.g. on output to a string in this case). It does not change the value of result.

Notionally, the string s can be stored in your database .... if the field represents a string rather than a numeric value.

Peter
  • 35,646
  • 4
  • 32
  • 74
-1

the value is stored 47.600002288 for precision, but when you want to use it you can use just N digits after the floating point, for example if the value is (47.600002288) in printf use:

printf("%.2f\n", result);

this will print 47.60, notice the .2 after % it tell the formatting function to print 2 number after the floating point.

Note that you can print it directly to a string using sprintf:

char s= malloc(sizeof(char)*10);
sprintf(s, "%.2f\n", result);
//s contains "47.60"

In this case you have to be aware of the malloc parameter i used sizeof(char)*10 this means that the character length must be under or equal 9 (cause the last character is reserved for string ending char \0).

younes zeboudj
  • 856
  • 12
  • 22