The task is as follows:

Enter an integer a and output the sum of squares of all numbers from 1 to a with a step of 0.1. (1 ^ 2 + 1.1 ^ 2 + 1.2 ^ 2 + ... + a ^ 2)

The solution algorithm is as follows:

result := 0 while (a >= 1) do begin result := result + a * a; a := a - 0.1; end; 

At the end of the program, the result should be:

 При a = 1.1 result = 2.21 При a = 3 result = 91.7 

The variable a , in any case, at the end of the program must be equal to 0.9 .

The problem is as follows. When a = 1.1 everything is correct, but starting from 1.2 and further, the program produces as a result 1 less than necessary: a = 3; result = 90.7 a = 3; result = 90.7 , at the same time, at the end of the program, a = 0.9(9) .

If the algorithm is modified: the variable a is multiplied by 10 after input, and then it is not a cycle that squares the expression a / 10 , but everything starts to work correctly (the second line in the cycle will be: a := a - 1 ).

What could be the problem?

  • problem in the representation of fractional numbers in binary form. In short - 0.2 it is impossible to imagine exactly. - kami
  • @kami, then the modified algorithm is the only solution to the problem? - nup
  • In your case - it is possible. But it is worth trying this: to compare real numbers, use Math.SameValue and Math.CompareValue (I think they are in D7). Emnip, there is an explanation for this effect on CO, but I didn’t find it on the move ... - kami

1 answer 1

The problem is that the numbers are represented in binary form. The decimal value 0.1 cannot be represented in binary form as a final fraction, it is equal to 0.0001100110011 ... 2 or 0.0 (0011) 2 in the standard notation of rational fractions.

Double-precision floating-point numbers contain 53 binary decimal places, the infinite part of the fraction is discarded. As a result, instead of the exact value of 0.1, we have the number 0.10000000000000055511151231257827021181583404541015625. If you print it with not very high accuracy, you will get 0.1, but this is only the result of rounding. When rounded to the 17th digit, 0.1000000000000001 is obtained, and the last digit is involved in the calculations. Therefore, two times subtracting from 1.2 a value of 0.1, you get a number less than 1.

There is no simple solution to such problems for all occasions. The simplest in your case will be emulation of numbers with a fixed comma, for example, as you did.

You can simplify the calculations by calculating the sums of squares of integers, and dividing the result by 100:

a 2 + (a + 0.1) 2 + (a + 0.2) 2 + ... =

(10a) 2/100 + (10a + 1) 2/100 + (10a + 2) 2/100 + ...

You can use libraries that provide work with rational numbers, with numbers in the decimal number system (like the decimal type in C #), or with numbers of high precision.