Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 7, 2017 07:10:40

UncleFather
Зарегистрирован: 2017-11-07
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Длинная арифметика

Всем привет!
Подскажите, пожалуйста, кто знает почему на Python 3.6 при попытке посчитать длинные целые числа, получается неверный ответ:

print(int(-9999999999 * 10000000002 / 2))
print(int(-(10**10-1) * (10**10+2) / (2**1)
>>-50000000005000003584
>>-50000000005000003584

А должно быть
-50000000004999999999
в обоих случаях.

Спасибо.

Офлайн

#2 Ноя. 7, 2017 07:26:15

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Длинная арифметика

Во втором питоне деление по дефолту целочисленное, то есть 10000000002 / 2 - целое, а в третьем результат деления по умолчанию дает float. Если вы точно знаете, что результат деления будет целым, то можно делить так 10000000002 // 2



Офлайн

#3 Ноя. 7, 2017 08:17:35

UncleFather
Зарегистрирован: 2017-11-07
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Длинная арифметика

FishHook
Во втором питоне деление по дефолту целочисленное, то есть 10000000002 / 2 - целое, а в третьем результат деления по умолчанию дает float. Если вы точно знаете, что результат деления будет целым, то можно делить так 10000000002 // 2

Спасибо, так сработало. Про целочисленное деление я что-то сразу не сообразил.

Но все же получается, если я буду считать в типе float, то ответ получится неверный. Почему так? Разве питон, когда считает во floate, отбрасывает какую-то часть числа?

Офлайн

#4 Ноя. 7, 2017 08:40:46

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Длинная арифметика

UncleFather
Почему так? Разве питон, когда считает во floate, отбрасывает какую-то часть числа?

Потому что у дробного числа всегда есть предел точности. Даже если вы возьмете ооооочень большое целое число, вы всегда знаете сколько байт памяти нужно, чтобы хранить это число. А сколько байт нужно для хранения иррациональных значений? Разумеется, всегда есть предел точности вычислений при операциях с float и double.



Офлайн

#5 Ноя. 7, 2017 10:36:24

UncleFather
Зарегистрирован: 2017-11-07
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Длинная арифметика

да как-то напрягает, когда java выдает одинаковые ответы

System.out.println(new BigDecimal("1000000000000000000000000002").divide(BigDecimal.valueOf(2)));
>>500000000000000000000000001
System.out.println(new BigInteger("1000000000000000000000000002").divide(BigInteger.valueOf(2)));
>>500000000000000000000000001

а питон - разные:
print(int(1000000000000000000000000002 / 2))
500000000000000006643777536
print(int(1000000000000000000000000002 // 2))
>>500000000000000000000000001

я понимаю, когда отбрасывается дробная часть…. но целую-то часть отбрасывать незачем. В ней же число знаков не бесконечно.

Получается, что если хочешь в питоне посчитать огроооомное число, но при этом результат деления не будет целым, то потеряешь в точности всё после 16-го знака? Или как-то можно в питоне считать (делить) числа, которые длиннее 16 знаков, получая нормальные ответы?

Спасибо за Ваши ответы и советы))).

Офлайн

#6 Ноя. 7, 2017 10:53:45

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Длинная арифметика

UncleFather
я понимаю, когда отбрасывается дробная часть…. но целую-то часть отбрасывать незачем.

Это потому что вы плохо представляете, как float хранится в памяти. Вот почитайте. Грубо говоря, float - это маленькая голова целого, длинный хвост дроби и степень двойки. Когда вы приводите float к целому вы побитово сдвигаете хвост на степень знаков.



Офлайн

#7 Ноя. 7, 2017 10:56:48

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Длинная арифметика

UncleFather
да как-то напрягает, когда java выдает одинаковые ответы
Потому что Decimal. Очень странно, что в java вы с удовольствием используете этот тип, а в питоне не хотите

    
from decimal import Decimal
print((Decimal(1000000000000000000000000002) / 2))
>>>500000000000000000000000001



Офлайн

#8 Ноя. 7, 2017 12:22:52

UncleFather
Зарегистрирован: 2017-11-07
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Длинная арифметика

FishHook
Потому что Decimal. Очень странно, что в java вы с удовольствием используете этот тип, а в питоне не хотите
Спасибо))), просто не знал про Decimal в питоне.
Значит, если мы просто считаем 1000000000000000000000000002 / 2, то питон считает это как обычный float и после преобразования int(1000000000000000000000000002 / 2) мы получим именно округленный float.
В то время, как Decimal(1000000000000000000000000002) сразу говорит интерпретатору, что считать нужно с такой точностью, сколько в числе знаков.

FishHook
Это потому что вы плохо представляете, как float хранится в памяти. Вот почитайте. Грубо говоря, float - это маленькая голова целого, длинный хвост дроби и степень двойки. Когда вы приводите float к целому вы побитово сдвигаете хвост на степень знаков.
Это-то я помню. Для меня вопрос заключался немного в другом. А именно - если везде пишут, что длинная арифметика встроена в питон, то значит, что под переменную float и int питон должен выделять не 32 бита, как в других языках (и даже не 64), а столько, сколько потребуется. Если для других языков объем памяти для хранения переменных четко прописан и найти это в сети достаточно легко, то для питона, если это где-то и записано, то еще нужно постараться найти. А поскольку сразу не нашел - отсюда и заблуждение.
Короче - нужно мне учить матчасть.
Спасибо еще раз за Ваши советы, теперь появилась какая-то ясность.

Последний вопрос - если есть подозрение, что мы выскочим из long-а, то в формуле, там где происходит первое действие, нужно прописать Decimal, а остальная часть уже сама будет считаться как Decimal?
g = 9999999999999999999999
Decimal(1 + g) / 2 * g

Офлайн

#9 Ноя. 7, 2017 12:28:50

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Длинная арифметика

UncleFather
что под переменную float и int питон должен выделять не 32 бита, как в других языках (и даже не 64), а столько, сколько потребуется
Ну тогда простая операция 1 / 3 сожрет всю память вашего компьютера



Офлайн

#10 Ноя. 7, 2017 14:11:54

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Длинная арифметика

UncleFather
Последний вопрос - если есть подозрение, что мы выскочим из long-а, то в формуле, там где происходит первое действие, нужно прописать Decimal, а остальная часть уже сама будет считаться как Decimal?
В питоне можно переопределять операторы. Понятно что Decimal(x) * 4 -> умножение вызовет метод у объекта Decimal и этот метод вернет опять Decimal. А 4 * Decimal(x) - нет.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version