user3394113
user3394113

Reputation: 123

objective c float increment wrong value

I have a query regarding floating value increment in loop.

I have following code

float add = 1.02f;
float counter = 0.0f;
for (int i = 0; i < 20; i++) {
    counter += add;
    NSLog(@"%f",counter);
}

While executing this loop I am getting following result

1.020000
2.040000
3.060000
4.080000
5.100000
6.120000
7.140000
8.160000
9.180000
10.200001
11.220001
12.240002
13.260002
14.280003
15.300003
16.320004
17.340004
18.360004
19.380005
20.400005

Here is expected result

1.020000
2.040000
3.060000
4.080000
5.100000
6.120000
7.140000
8.160000
9.180000
10.200000
11.220000
12.240000
13.260000
14.280000
15.300000
16.320000
17.340000
18.360000
19.380000
20.400000

Why i am getting some floating point in loop without adding it.

I need to loop more then 1000 times. And I want the value in float variable.

Thanks in advance.

Upvotes: 0

Views: 1433

Answers (4)

Merlevede
Merlevede

Reputation: 8180

Floating point numbers use four bytes = 32 bits.

  • 1 bit for sign
  • 8 bits for exponent
  • 23 bits for mantissa

Precision: The number of decimal digits precision is calculated via number_of_mantissa_bits * Log10(2). Thus ~7.2 and ~15.9 for single and double precision respectively.

That's why you start to see rounding errors on the 7th digit

Source link.

Upvotes: 0

Gavin
Gavin

Reputation: 8200

Floating point number representations in computers are approximations, they are not exact. Sometimes you end up trying to display a number that can't be exactly represented in the computer's floating point number implementation, so it gives you an approximation. Also you get small arithmetic errors from repeated multiplications, additions, etc. of floating point numbers. The best you can do is to use doubles, which have more precision than floats do. In special circumstances, you could also represent your data in a different format and just change how you display it to the user to fit what they expect. For example, when working with dollars and cents, you could just store a total as a number of cents (which would be only an integer) and then format it to be shown as dollars and cents correctly for the user. There's no floating point rounding issues happening then.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727087

This happens because float cannot represent the values that you have with exact precision. There are two simple ways of fixing this:

  • Represent the number as 100 times the target value, and use integers - 1.02 becomes 102, 2.04 becomes 204, and so on.
  • Use NSDecimalNumber to represent your numbers - Unlike float, NSDecimalNumber can represent all your values with full precision.

Here is how to implement the first approach:

int add = 102;
int counter = 0;
for (int i = 0; i < 20; i++) {
    counter += add;
    NSLog(@"%d.%d", counter/100, counter%100);
}

Here is how to implement the second approach:

NSDecimalNumber add = [NSDecimalNumber decimalNumberWithString:@"1.02"];
NSDecimalNumber counter = [NSDecimalNumber zero];
for (int i = 0; i < 20; i++) {
    counter = [counter decimalNumberByAdding:add];
    NSLog(@"%@", counter);
}

Upvotes: 6

Caleb
Caleb

Reputation: 125037

Why i am getting some floating point in loop without adding it.

Because float is a binary type that doesn't represent decimal values exactly. Rather than trying to explain completely and correctly, let me point you to the well-known paper What Every Computer Scientist Should Know About Floating Point Arithmetic.

Upvotes: 3

Related Questions