LINUX.ORG.RU

При умножении n на 0.1 после(меньше) 0.1 появляется «выхлоп» в виде маленького остатка.

 


1

3
a = 1000
count = 0
while count != 15: 
    count = count + 1
    a = a * 0.1
    print('====\n#', count)
    print('a =', a)
____
Result: 

====
# 1
a = 100.0
====
# 2
a = 10.0
====
# 3
a = 1.0
====
# 4
a = 0.1
====
# 5
a = 0.010000000000000002
====
# 6
a = 0.0010000000000000002
====
# 7
a = 0.00010000000000000003
====
# 8
a = 1.0000000000000004e-05

etc

Ну и что? Используй round.

FIL ★★★★
()
Ответ на: комментарий от kramh

И еще вопрос: почему так происходит? Хотя бы кратко

Вот тут доходчиво объяснено же:

http://habrahabr.ru/post/112953/

А пофиксить как можно, кроме округления?

Только если не использовать чисел с плавающей запятой, независимо от ЯП.

Psych218 ★★★★★
()
Последнее исправление: Psych218 (всего исправлений: 1)
Ответ на: комментарий от Psych218

В принципе, думаю, можно написать отдельную часть кода, которая будет это фиксить. Т.е. вычитать. Ведь если числа очень большие(т.е. маленькие), то этот остаток может сильно помешать.

kramh
() автор топика
Ответ на: комментарий от kramh

А пофиксить как можно, кроме округления?

Представь как строку и возьми символов столько, сколько тебе нужно (это если без округления), в том числе используя format и аналоги.

alozovskoy ★★★★★
()

Используй Decimal:

from decimal import Decimal

a = Decimal(1000)
count = 0
while count != 15:
    count = count + 1
    a = a * Decimal('0.1')
    print('====\n#', count)
    print('a =', a)

Выхлоп:

('====\n#', 1)
('a =', Decimal('100.0'))
('====\n#', 2)
('a =', Decimal('10.00'))
('====\n#', 3)
('a =', Decimal('1.000'))
('====\n#', 4)
('a =', Decimal('0.1000'))
('====\n#', 5)
('a =', Decimal('0.01000'))
('====\n#', 6)
('a =', Decimal('0.001000'))
('====\n#', 7)
('a =', Decimal('0.0001000'))
('====\n#', 8)
('a =', Decimal('0.00001000'))
('====\n#', 9)
('a =', Decimal('0.000001000'))
('====\n#', 10)
('a =', Decimal('1.000E-7'))
('====\n#', 11)
('a =', Decimal('1.000E-8'))
('====\n#', 12)
('a =', Decimal('1.000E-9'))
('====\n#', 13)
('a =', Decimal('1.000E-10'))
('====\n#', 14)
('a =', Decimal('1.000E-11'))
('====\n#', 15)
('a =', Decimal('1.000E-12'))

holuiitipun
()

Используй тDecimal для точных вычислений. Только он тормозит чуток.

Deleted
()
Ответ на: комментарий от kramh

В принципе, думаю, можно написать отдельную часть кода, которая будет это фиксить. Т.е. вычитать. Ведь если числа очень большие(т.е. маленькие), то этот остаток может сильно помешать.

Ты так ничего и не понял. Ну не может твой несчастный double запомнить число 0.010000000000000000. Либо больше, либо меньше. Ты можешь вычитать 0.010000000000000002 - 0.000000000000000002 хоть до посинения, но 0.01 никогда не получишь.

Waterlaz ★★★★★
()
Ответ на: комментарий от mix_mix

Они «переведутся» перед тем как программисты исчезнут

kramh
() автор топика
Ответ на: комментарий от mix_mix

Так что это, в принципе, даже хорошо

kramh
() автор топика
Ответ на: комментарий от Mahmood

Да какая разница, как проводить сложение/вычитание/умножение?

ТС хочет, чтобы a = 0.01, чего не может быть с double в принципе.

Waterlaz ★★★★★
()
Ответ на: комментарий от Waterlaz

Разумеется, не может. Но цель наша, программистская - решить задачу максимально хорошо в рамках доступных ресурсов, так? Идеальной точности не получить, но пренебрежение этим фактором при проектировании алгоритма может повлечь за собой код, выдающий совершенно левый результат.

Mahmood
()
Ответ на: комментарий от Deleted

Я ждал здесь с этим комментарием именно тебя)

cdshines ★★★★★
()
Ответ на: комментарий от kramh

А пофиксить как можно, кроме округления?

Замени делитель (0.1) дробью с целыми числами, т.е. дели на 10.

arson ★★★★★
()
Ответ на: комментарий от kramh
>>> a
0.010000000000000002
>>> b = a - 0.000000000000000002
>>> '%.20f' % b
'0.01000000000000000021'

Почему?

Потому что 1/10 в двоичной системе исчисления — периодическая дробь. Ну прочти же ты уже про числа с плавающей точкой.

Waterlaz ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Прочитал хабростатью. Но остались еще открытые вопросы. Например, если использовать двойную точность я смогу этого избежать? И есть ли сишный аналог double для python, или он сразу в двойной работает?

kramh
() автор топика
Ответ на: комментарий от I-Love-Microsoft

Т.е., я понимаю, что до определенной степени я все-таки смогу решать эту проблему с двойной точностью. Но в python она по дефолту стоит?

kramh
() автор топика
Ответ на: комментарий от kramh

Уйдёт, а потом опять прийдёт. Отчего итоговый результат исказится ещё больше. Поэтому если нужна точность - либо fixed point, либо gmp

frame ★★★
()
Ответ на: комментарий от frame

fixed point в python только в помощью сишной библиотеки «Decimal» можно реализовать, как я знаю. В принципе, на этом варианте и остановлюсь

kramh
() автор топика
Ответ на: комментарий от kramh

И есть ли сишный аналог double для python, или он сразу в двойной работает?

В твоем питоне и так double.

Waterlaz ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.