Математические вычисления, стоящие за использованием (%, //) в python путем применения (Decimal (), числа со знаком)? - PullRequest
0 голосов
/ 13 октября 2018

Я пытался понять математику вычислений с использованием операторов / и // и%, выполнив несколько испытаний, и обнаружил, что результаты похожи на калькулятор только при использовании Decimal (), но без него результаты немного запутанные, я попытался добавитькомментарии #No Idea к моему коду, чтобы пометить точки, которые я не понимаю, например:

  1. в этом испытании для оператора%, применяя число со знаком и без знака, результаты с и безDecimal () результаты:

    >>> 9%5    #This result will be the reminder
    4         
    >>> (-9)%5    #No Idea
    1
    >>> Decimal(9)% Decimal(5)    #This result will be the reminder
    Decimal('4')  
    >>> Decimal(-9)% Decimal(5)    #The result will be the signed reminder
    Decimal('-4')
    
  2. в этом испытании для оператора // с использованием числа со знаком и без знака с и без десятичного разделителя () результаты:

    >>> 9//5    #int result
    1
    >>> -9//5    #No Idea
    -2
    >>> Decimal(9)/Decimal(5)    #Same result as using calculator
    Decimal('1.8')
    >>> Decimal(-9)//Decimal(5)    #No Idea
    Decimal('-1')
    

Пожалуйста, примите во внимание, что этот вопрос не является дубликатом, и я провел некоторое исследование, чтобы получить ответ, но нашел несколько ответов на вопросы, которые объясняют только оператор //, использующий только числа с положительными знаками, и неt включает информацию о числах с отрицательными знаками или использовании десятичной дроби () и не имеет ответа об операторе%.

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

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

Объяснение поведения целых чисел

Из документации по питону :

Деление целых чисел дает число с плавающей запятой, тогда как деление целых чисел по полу приводит к целому числу;результатом является математическое деление с применением к полу функции «floor».

Следовательно, целочисленное деление (//) отрицательного отрицательного и положительного числа работает следующим образом:

-9 // 5 == floor(-9 / 5) == floor(-1.8) == -2

Оператор по модулю является остатком от целочисленного деления, то есть x % y = x - x // y * y.В вашем примере:

-9 % 5 == -9 - (-9 // 5 * 5) == (-9) - (-2 * 5) == (-9) - (-10) == 1

В документации также сказано:

Оператор по модулю всегда выдает результат с тем же знаком, что и его второй операнд (или ноль);абсолютное значение результата строго меньше, чем абсолютное значение второго операнда.

Но это естественно из формулы, приведенной выше, например:

9 % -5 == 9 - (9 // (-5) * (-5)) == 9 - (-2 * (-5)) == 9 - 10 == -1

decimal.Decimal отличается

Документация хорошо объясняет разницу:

Есть небольшие отличия между арифметикой для десятичных объектов и арифметикой для целых чисел и чисел с плавающей точкой.Когда оператор остатка % применяется к десятичным объектам, знак результата является знаком дивиденда, а не знаком делителя:

>>> (-7) % 4
1
>>> Decimal(-7) % Decimal(4)
Decimal('-3')

Оператор целочисленного деления // ведет себя аналогичновозвращая целую часть истинного фактора (усеченного до нуля), а не его пол, чтобы сохранить обычную идентичность x == (x // y) * y + x % y:

>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')
0 голосов
/ 13 октября 2018

Как я понимаю вопрос, ОП задает вопрос о различном поведении между целыми числами Python и Decimal с.Я не думаю, что для этого есть веская причина.Оба варианта возможны, но для пользователя немного странно, что они различаются.

Давайте назовем числитель n, знаменатель d и разделим результат на результат интергера i иостаток r.Это означает, что

n // d = i
n % d = r

Чтобы операции имели смысл, нам нужно

i * d + r == n

Для n = -9 и d = 5 мы видим, что это поддерживается как для i = -1, r = -4, так и длядля i = -2, r = 1, как видно из

(i = -1, r = -4) => -1 * 5 + -4 == -9
(i = -2, r = 1) => -2 * 5 + 1 == -9

Теперь в Python целочисленное деление определяется как всегда усеченное до минус бесконечности (вниз), а реализация Decimal выбрала округление до нуля.Это означает, что положительные значения усекаются / округляются в меньшую сторону, тогда как отрицательные значения округляются в большую сторону.

Округление до нуля является выбором, сделанным также на языке Си.Тем не менее, мое личное мнение заключается в том, что выбор Python гораздо более разумный, особенно исходя из аппаратного обеспечения.И учитывая, что это выбор, сделанный в Python, я думаю, что это странно (и плохо), что Decimal решил поступить так же, как в языке C.

...