Ответ 1
Это не имеет ничего общего с Python - вы увидите одно и то же поведение на любом языке, используя вашу аппаратную двоичную арифметику с плавающей запятой. Сначала прочитайте документы.
После того, как вы прочтете это, вы поймете, что вы не добавляете одну сотую в свой код. Это именно то, что вы добавляете:
>>> from decimal import Decimal
>>> Decimal(.01)
Decimal('0.01000000000000000020816681711721685132943093776702880859375')
Эта строка показывает точное десятичное значение бинарного плавающего ( "двойной точности" в С) приближения к точной десятичной величине 0,01. То, что вы действительно добавляете, немного больше, чем 1/100.
Управление числовыми ошибками с плавающей запятой - это поле под названием "численный анализ" и является очень большой и сложной темой. До тех пор, пока вы напуганы тем фактом, что поплавки просто приближаются к десятичным значениям, используйте модуль decimal
. Это уберет для вас мир "мелких проблем". Например, учитывая эту небольшую модификацию вашей функции:
from decimal import Decimal as D
def sqrt(num):
root = D(0)
while root * root < num:
root += D("0.01")
return root
то
>>> sqrt(4)
Decimal('2.00')
>>> sqrt(9)
Decimal('3.00')
Это не совсем точно, но может быть менее неожиданным в простых примерах, потому что теперь он добавляет ровно одну сотую.
Альтернативой является придерживаться float и добавлять что-то точно представляемое как двоичный float: значения формы I/2**J
. Например, вместо добавления 0,01 добавить 0,125 (1/8) или 0,0625 (1/16).
Затем найдите "метод Ньютона" для вычисления квадратных корней; -)