Неправильна математика з Python?


78

Тільки починаючи з Python, то це, мабуть, моя помилка, але ...

Я випробовую Python. Мені подобається використовувати його як калькулятор, і я повільно переглядаю деякі підручники.

Сьогодні я натрапив на щось дивне. Я хотів дізнатись 2013 * 2013, але написав не те, написав 2013 * 013, і отримав таке:

>>> 2013*013
22143

Я перевірив свій калькулятор, і 22143 - це неправильна відповідь! 2013 * 13 передбачається 26169.

Чому Python дає мені неправильну відповідь? Мій старий калькулятор Casio цього не робить ...


2
пов'язані з : stackoverflow.com/q/13013638/748858
mgilson

6
+1 за те, що насправді помітив. Я знав, що це вісімкове число, але якби я не знав, я б зараз думав, що 2013 * 13 був 22143. Як ви виявили, що це була неправильна відповідь?
11684

11
Я ще деякий час займався розумовою математикою ще в старшій школі, і вважав, що 22143 трохи менший, ніж повинен бути. Тож я перевірив за допомогою мого надійного калькулятора.
James Elegan

2
+1 за довіру своєму хорошому Оле '.
Шон Олред

13
@ 11684 Якщо остання цифра в обох числах дорівнює 3, остання цифра добутку повинна бути 9. Математика початкової школи ...
Олександр

Відповіді:


137

Через вісімкову арифметику 013 насправді є цілим числом 11.

>>> 013
11

З початковим нулем 013інтерпретується як число-8 і 1 * 8 1 + 3 * 8 0 = 11.

Примітка: ця поведінка була змінена в python 3 . Ось особливо відповідна цитата з PEP 3127

Вісімкове представлення за замовчуванням цілих чисел мовчки заплутало людей, які не знайомі з мовами, подібними на С. Навмисно легко ненавмисно створити цілочисельний об’єкт з неправильним значенням, тому що „013“ означає „десяткову 11“, а не „десяткову 13“ для самої мови Python, що не означає значення, яке більшість людей надавали б цьому буквалу .


14
@JamesElegan: Можливо, це одна з причин, чому Python 3 робить 0123синтаксис незаконним і завжди вимагає 0o123.
Тім Пітцкер

3
Так, 0префікс, за яким слідує 0-8, є вісімковим. 0xпрефікс, за яким слідує 0-9a-f - це шістнадцятковий.
Фрамбот,

97
Чому програмісти завжди плутають Хелловін та Різдво? Тому що DEC25 == OCT31! Нюк ньюк ньюк.
Фрамбот,

16
@JoeFrambach, 0префікс з подальшим 0- 7 восьмеричний :)
Марк Толон

5
Доброзичливий диктатор не скопіював з Ліспа належним чином перший раз. Ці речі повинні бути чіткими та чіткими: #xFF, # o777, # b1011.
Каз

36

013- восьмеричний цілочисельний літерал (еквівалентний десятковому цілочисельному літералу 11), що зумовлений початковим 0.

>>> 2013*013
22143
>>> 2013*11
22143
>>> 2013*13
26169

Дуже часто (звичайно, в більшості мов, якими я знайомий) вісімкові цілочисельні літерали починаються з, 0а шістнадцяткові цілочисельні літерали починаються з 0x. Через точну плутанину, яку ви зазнали, Python 3 викликає помилку SyntaxError:

>>> 2013*013
  File "<stdin>", line 1
    2013*013
           ^
SyntaxError: invalid token

і вимагає 0oабо 0Oзамість цього:

>>> 2013*0o13
22143
>>> 2013*0O13
22143 

Дякую за відповідь! Я думаю, що це вісімкове дещо заплутане, але принаймні зараз я про це знаю :)
Джеймс Елеган

3
Ласкаво просимо. Як зазначалося у відповіді мого та @ wim, спільнота Python робить все можливе, щоб мінімізувати плутанину для початківців навколо восьмеричних літералів з Python 3. Тим не менше, це дуже добре знати - ви можете бути впевнені, що натрапите Знову вісімкові літерали з префіксом 0, будь то на Python 2.X чи іншій мові.
Даршан Рівка Уіттл,

2
PEP 3127 є трохи кумедним прочитанням у цьому відношенні ... наприклад, "новий користувач Python може (наразі) викликати містифікацію через відкладене відкриття того, що його номери не працюють належним чином, ми можемо це виправити, негайно пояснивши йому, що Python не любить провідних нулів (сподіваємось, з розумним повідомленням!), або ми можемо передати цей досвід викладання інтерпретатору JavaScript у браузері Internet Explorer і дозволити йому спробувати там налагодити свою проблему. "
wim


5

Це здебільшого просто трохи розширюється на відповідь @ Wim, але Python вказує основу цілочисельних літералів, використовуючи певні префікси. Без префікса цілі числа інтерпретуються як такі, що знаходяться в основі-10. З "0x" ціле число буде інтерпретовано як шістнадцяткове число int. Повна специфіка граматики тут, хоча трохи складно зрозуміти, якщо ви не знайомі з формальними граматиками: http://docs.python.org/2/reference/lexical_analysis.html#integers

У таблиці, по суті, сказано, що якщо ви хочете довге значення (тобто таке, яке перевищує ємність звичайного int), напишіть число, за яким слід літера «L» або «l»; якщо ви хочете, щоб ваш номер інтерпретувався в десятковій точці, напишіть це число звичайно (без початкових 0); якщо ви хочете, щоб його інтерпретували вісімковою лінією, додайте префікс до "0", "0o" або "0O"; якщо ви хочете в шістнадцятковій формі, додайте до неї префікс "0x"; і якщо ви хочете, щоб це було в двійковому вигляді, поставте перед ним префікс "0b" або "0B".


Здається, Python додає L автоматично, коли я ввожу справді великі числа (наприклад, 9999999999999999999999999, але не як 3333333333). Чи є час, коли мені довелося б це додати самому?
Джеймс Елеган,

@JamesElegan лише в тому випадку, якщо ви використовуєте шалено стару версію Python. А в Python 3 L повністю зник, як і всі інші відмінності між типами int та long.
lvc

Python 2.7 не шалено старий, я так вважаю? Тому мені ніколи не потрібно додавати L. (Я постійно чую хороші речі про Python 3, можливо, мені слід просто встановити та використовувати це?)
Джеймс Елеган,

@JamesElegan Я не можу знайти жодної точної інформації про те, яка попередня версія вимагала суфікса для літералів, які були більшими, ніж міг би вміститися в int(і я, можливо, помиляюсь, що їх є) - моя власна пам'ять сягає настільки, наскільки справедливо впевнений, що 2.4 це не потрібно. Але так, до Python 3, як правило, варто перейти, якщо ви не залежате від жодної бібліотеки, яка ще не перенесена.
lvc

Python 2.7 - це остання версія Python 2; насправді, 2.7.4 вийшов якраз на цих вихідних. Python 3 суттєво відрізняється від Python 2, але, зрештою, більшість кодів Python буде записаний як код Python 3 у недалекому майбутньому, або, принаймні, це, здається, є метою. Отже, якщо ви тільки починаєте, і ви можете вибрати, якому з них навчитися, я б рекомендував або 3, або обидва 2 і 3.
Kyle Strand
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.