Проблема с циклом For в Visual Basic при инкременте 0.1

Коллеги, добрый день. Столкнулся со странной проблемой цикла For при написании макроса в Visual Basic.

Для примера, имею я вот такой код:

Sub Test_for()
    Dim cell As Range
    Dim counter As Integer
    Set cell = Range("A1")

'Первый цикл For
    counter = 0
    For i = 0 To 1 Step 0.1
        cell.Offset(counter, 0).Value = i
        counter = counter + 1
    Next i

'Второй цикл For
    counter = 0
    For j = 0 To 2 Step 0.1
        cell.Offset(counter, 1).Value = j
        counter = counter + 1
    Next j
'Третий цикл For
    counter = 0
    For k = 0.1 To 2.1 Step 0.1
        cell.Offset(counter, 1).Value = k
        counter = counter + 1
    Next k
End Sub

Так вот для первого цикла имею вывод вида от 0 до 1 (все верно), НО! для второго цикла имею вывод от 0 до 1,9 (но должно быть до 2). Для третьего цикла вывод от 0.1 до 2 (но должно быть до 2.1)!

Коллеги, кто разбирается в нюансах VB, подскажите, что я делаю не так, какие мануалы покурить. Для меня такое поведение циклов непонятно.


Ответы (1 шт):

Автор решения: CrazyElf

Числа с плавающей точкой имеют ограниченную точность. На последней итерации у вас переменная цикла принимает значение не ровно 2.0, а, например, 2.000000000001 и уже не попадает в верхнюю границу цикла, заданную как 2.

Правильнее всего тут спользовать тип decimal, который представляет дробные числа точно в десятичной системе, для этого использовать постфикс D у чисел:

For j = 0D To 2D Step 0.1D
    cell.Offset(counter, 1).Value = j
    counter = counter + 1
Next j

Но можно сделать и более кустарно, если тип decimal по каким-то причинам не доступен:

  • Не использовать числа с плавающей точкой, делать цикл в целых числах от 0 до 20 и внутри цикла получать нужное значение переменной, деля переменную цикла на 10
  • Задать верхнюю границу цикла с небольшим запасом - например, не 2, а 2.05, чтобы это было число заведомо больше 2, но меньше значения для следующей итерации, т.е. чем 2.1
→ Ссылка