ugur
ugur

Reputation: 842

Multiplying two floats doesn't give exact result

I am trying to multiply two floats as follows:

float number1 = 321.12;
float number2 = 345.34;
float rexsult = number1 * number2;

The result I want to see is 110895.582, but when I run the code it just gives me 110896. Most of the time I'm having this issue. Any calculator gives me the exact result with all decimals. How can I achive that result?

edit : It's C code. I'm using XCode iOS simulator.

Upvotes: 1

Views: 16073

Answers (4)

Agent_L
Agent_L

Reputation: 5411

  • floating point variables are only approximate representation, not precise one. Not every number can "fit" into float variable. For example, there is no way to put 1/10 (0.1) into binary variable, just like it's not possible to put 1/3 into decimal one (you can only approximate it with endless 0.33333)
  • when outputting such variables, it's usual to apply many rounding options. Unless you set them all, you can never be sure which of them are applied. This is especially true for << operators, as the stream can be told how to round BEFORE <<.

Printf also does some rounding. Consider http://codepad.org/LLweoeHp:

float t = 0.1f;
printf("result: %f\n", t);
--
result: 0.100000

Well, it looks fine. Why? Because printf defaulted to some precision and rounded up the output. Let's dial in 50 places after decimal point: http://codepad.org/frUPOvcI

float t = 0.1f;
printf("result: %.50f\n", t);
--
result: 0.10000000149011611938476562500000000000000000000000

That's different, isn't it? After 625 the float ran out of capacity to hold more data, that's why we see zeroes. A double can hold more digits, but 0.1 in binary is not finite. Double has to give up, eventually: http://codepad.org/RAd7Yu2r

double t = 0.1;
printf("result: %.70f\n", t);
--
result: 0.1000000000000000055511151231257827021181583404541015625000000000000000

In your example, 321.12 alone is enough to cause trouble: http://codepad.org/cgw3vUKn

float t = 321.12f;
printf("and the result is: %.50f\n", t);
result: 321.11999511718750000000000000000000000000000000000000

This is why one has to round up floating point values before presenting them to humans.

Calculator programs don't use floats or doubles at all. They implement decimal number format. eg:

struct decimal
{
     int mantissa; //meaningfull digits
     int exponent; //number of decimal zeroes
};

Ofc that requires reinventing all operations: addition, substraction, multiplication and division. Or just look for a decimal library.

Upvotes: 1

Dietrich Epp
Dietrich Epp

Reputation: 213258

There's a lot of rounding going on.

float a = 321.12; // this number will be rounded
float b = 345.34; // this number will also be rounded
float r = a * b;  // and this number will be rounded too
printf("%.15f\n", r);

I get 110895.578125000000000 after the three separate roundings.

  1. If you want more than 6 decimal digits' worth of precision, you will have to use double and not float. (Note that I said "decimal digits' worth", because you don't get decimal digits, you get binary.) As it stands, 1/2 ULP of error (a worst-case bound for a perfectly rounded result) is about 0.004.

  2. If you want exactly rounded decimal numbers, you will have to use a specialized decimal library for such a task. A double has more than enough precision for scientists, but if you work with money everything has to be 100% exact. No floating point numbers for money.

Unlike integers, floating point numbers take some real work before you can get accustomed to their pitfalls. See "What Every Computer Scientist Should Know About Floating-Point Arithmetic", which is the classic introduction to the topic.

Edit: Actually, I'm not sure that the code rounds three times. It might round five times, since the constants for a and b might be rounded first to double-precision and then to single-precision when they are stored. But I don't know the rules of this part of C very well.

Upvotes: 11

Alexey Frunze
Alexey Frunze

Reputation: 62048

You will never get the exact result that way.

First of all, number1 ≠ 321.12 because that value cannot be represented exactly in a base-2 system. You'll need an infinite number of bits for it.

The same holds for number2 ≠ 345.34.

So, you begin with inexact values to begin with.

Then the product will get rounded because multiplication gives you double the number of significant digits but the product has to be stored in float again if you multiply floats.

You probably want to use a 10-based system for your numbers. Or, in case your numbers only have 2 decimal digits of the fractional, you can use integers (32-bit integers are sufficient in this case, but you may end up needing 64-bit):

32112 * 34534 = 1108955808.

That represents 321.12 * 345.34 = 110895.5808.

Upvotes: 3

Man of One Way
Man of One Way

Reputation: 3980

Since you are using C you could easily set the precision by using "%.xf" where x is the wanted precision.

For example:

float n1 = 321.12;
float n2 = 345.34;
float result = n1 * n2;

printf("%.20f", result);

Output:

110895.57812500000000000000

However, note that float only gives six digits of precision. For better precision use double.

Upvotes: 1

Related Questions