Я виявив у Python дивну поведінку щодо від’ємних чисел:
>>> -5 % 4
3
Хтось може пояснити, що відбувається?
Я виявив у Python дивну поведінку щодо від’ємних чисел:
>>> -5 % 4
3
Хтось може пояснити, що відбувається?
..., -9, -5, -1, 3, 7, ...
math.fmod
таку ж поведінку, як у C або Java.
Відповіді:
На відміну від C або C ++, модульний оператор Python ( %
) завжди повертає число, що має той самий знак, що і знаменник (дільник). Ваш вираз дає 3, тому що
(-5) / 4 = -1,25 -> підлога (-1,25) = -2
(-5)% 4 = (-2 × 4 + 3)% 4 = 3.
Його вибирають замість поведінки С, оскільки неотрицательний результат часто є більш корисним. Прикладом є обчислення днів тижня. Якщо сьогодні вівторок (день №2), який день тижня за N днів до цього? У Python ми можемо обчислювати за допомогою
return (2 - N) % 7
але в C, якщо N ≥ 3, ми отримуємо від’ємне число, яке є недійсним числом, і нам потрібно вручну виправити його, додавши 7:
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
(Див. Http://en.wikipedia.org/wiki/Modulo_operator, щоб визначити знак результату для різних мов.)
Ось пояснення від Гвідо ван Россума:
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
По суті, це так, що a / b = q із залишком r зберігає співвідношення b * q + r = a та 0 <= r <b.
a
, позитивними b
, тоді як підлоги Python. Це завжди правда abs(r) < b
, і вони перешкоджають цьому r <= 0
.
Не існує одного найкращого способу обробки цілочисельного ділення та модифікацій з від’ємними числами. Було б непогано, якби a/b
була однаковою величиною і протилежним знаком (-a)/b
. Було б непогано, якби a % b
це справді було за модулем b. Оскільки ми справді хочемо a == (a/b)*b + a%b
, перші два несумісні.
Який з них зберегти - це складне питання, і є аргументи для обох сторін. C і C ++ округляють ціле ділення до нуля (так a/b == -((-a)/b)
), і, очевидно, Python цього не робить.
Як зазначалося, Python за модулем робить обґрунтовано виняток із конвенцій інших мов.
Це надає негативним числам безперебійну поведінку, особливо в комбінації з //
оператором цілочисельного ділення, як це %
часто відбувається за модулем (як у математиці. Divmod ):
for n in range(-8,8):
print n, n//4, n%4
Виробляє:
-8 -2 0
-7 -2 1
-6 -2 2
-5 -2 3
-4 -1 0
-3 -1 1
-2 -1 2
-1 -1 3
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
%
завжди виводить нуль або позитив *//
завжди обертається до негативної нескінченності* ... поки правильний операнд додатний. З іншого боку11 % -10 == -9
У python оператор modulo працює так.
>>> mod = n - math.floor(n/base) * base
тож результат (для вашого випадку):
mod = -5 - floor(-1.25) * 4
mod = -5 - (-2*4)
mod = 3
тоді як інші мови, такі як C, JAVA, JavaScript, використовують скорочення замість підлоги.
>>> mod = n - int(n/base) * base
в результаті чого:
mod = -5 - int(-1.25) * 4
mod = -5 - (-1*4)
mod = -1
Якщо вам потрібна додаткова інформація про округлення в python, прочитайте це .
За модулем, класи еквівалентності для 4:
Ось посилання на поведінку модуля з від’ємними числами . (Так, я погуглив)
Я також думав, що це дивна поведінка Python. Виявляється, я погано вирішував поділ (на папері); Я давав значення 0 для фактора і значення -5 для залишку. Жахливо ... Я забув геометричне зображення цілих чисел. Згадуючи геометрію цілих чисел, задану числовим рядком, можна отримати правильні значення для частки та залишку та перевірити, чи добре працює поведінка Python. (Хоча я припускаю, що ви вже давно вирішили своє занепокоєння).
Варто також згадати, що також поділ у python відрізняється від C: Поміркуйте
>>> x = -10
>>> y = 37
в С ви очікуєте результату
0
що таке x / y у python?
>>> print x/y
-1
а% за модулем - не залишок! Тоді як x% y в С дає
-10
python дає.
>>> print x%y
27
Ви можете отримати обидва, як у C
Поділ:
>>> from math import trunc
>>> d = trunc(float(x)/y)
>>> print d
0
І залишок (з використанням ділення зверху):
>>> r = x - d*y
>>> print r
-10
Це обчислення, можливо, не найшвидше, але воно працює для будь-яких комбінацій знаків x та y для досягнення тих самих результатів, що і в C, а також дозволяє уникнути умовних тверджень.