Чи є особливе значення для 16331239353195370.0?


89

Використовуючи, import numpy as npя це помітив

np.tan(np.pi/2)

дає номер у заголовку, а ні np.inf

16331239353195370.0

Мені цікаво це число. Це пов’язано з деяким параметром точності системи? Чи міг я це з чогось обчислити? (Я думаю про те, як щось подібне до sys.float_info)

РЕДАГУВАТИ: Той самий результат справді відтворюється в інших середовищах, таких як Java, октака, матлаб ... Однак запропонований обман не пояснює, чому.



10
Мені не подобається така відповідь - вона повністю хвиляста, насправді не пояснює причину. "Ну, загар (pi / 2) в радіанах по суті нескінченний, чи не так?" як просили тут OP - - відповідь нічого про те, чому не пояснює це не насправді np.inf. Але просто не лише пояснити, чому це не так, але також пояснити, чому відповідь саме те, що було побачено - і я так зробив ;-)
Тім Пітерс,

Відповіді:


119

piне точно представляється як Python float (такий самий, як doubleтип платформи C ). Використовується найближче репрезентативне наближення.

Ось точне наближення, яке використовується у моїй коробці (можливо, така ж, як і у вашій коробці):

>>> import math
>>> (math.pi / 2).as_integer_ratio()
(884279719003555, 562949953421312)

Щоб знайти тангенс цього співвідношення, я зараз перейду до wxMaxima:

(%i1) fpprec: 32;
(%o1) 32
(%i2) tan(bfloat(884279719003555) / 562949953421312);
(%o2) 1.6331239353195369755967737041529b16

Отже, по суті ідентичний тому, що ви отримали. Бінарне наближення до pi/2використовуваного трохи менше математичного ("нескінченна точність") значення pi/2. Таким чином, ви отримаєте дуже великий тангенс замість infinity. Обчислене tan()підходить для фактичного введення!

З абсолютно тих самих причин, наприклад,

>>> math.sin(math.pi)
1.2246467991473532e-16

не повертає 0. Наближення math.piтрохи менше ніж pi, і відображений результат є правильним, враховуючи цю істину.

ІНШІ ШЛЯХИ ПЕРЕГЛЯДУ math.pi

Існує кілька способів побачити точне наближення, яке використовується:

>>> import math
>>> math.pi.as_integer_ratio()
(884279719003555, 281474976710656)

math.pi точно дорівнює математичному ("нескінченна точність") значення цього коефіцієнта.

Або як точний плаваючий знак у шістнадцятковій нотації:

>>> math.pi.hex()
'0x1.921fb54442d18p+1'

Або способом, який найлегше зрозуміти майже кожному:

>>> import decimal
>>> decimal.Decimal(math.pi)
Decimal('3.141592653589793115997963468544185161590576171875')

Незважаючи на те, що це може бути не відразу очевидним, кожен кінцевий двійковий плаваючий спосіб точно представляється як кінцевий десятковий плаваючий знак (зворотне не відповідає дійсності; наприклад, десятковий 0.1не точно представляється як кінцевий двійковий плаваючий знак), і Decimal(some_float)конструктор видає точний еквівалент.

Ось справжнє значення, за piяким слідує точне десяткове значення math.pi, а каретка на третьому рядку вказує на першу цифру, де вони відрізняються:

true    3.14159265358979323846264338327950288419716939937510...
math.pi 3.141592653589793115997963468544185161590576171875
                         ^

math.piзараз однаковий у вікнах "майже всіх", оскільки майже всі вікна зараз використовують однаковий двійковий формат із плаваючою комою (подвійна точність IEEE 754). Ви можете скористатися будь-яким із наведених вище способів, щоб підтвердити це на вашій коробці або знайти точне наближення, яке використовується, якщо ваша коробка є винятком.


@Tim Peters - Це абсолютно зрозуміло. Для повноти я здогадуюсь, що це представлення np.piє найближчим раціональним поданням до епсилону системи?
Aguy

3
Якщо припустити, що воно np.piмає таке ж значення, як і значення Python math.pi(я не перевіряв, але ви можете ;-)), це найближче значення до математичного pi, яке можна представити у C doubleвласному форматі з плаваючою комою платформи . Це означає, що IEEE 754 має подвійну точність майже на всіх коробках зараз, і тому найближчий двійковий плаваючий з 53 бітами точності (мантиси). Отже, набір обґрунтувань обмежений формою, +/- I * 2**Jде ціле число Iдорівнює 0 або 2**52 <= I < 2**53, а діапазон цілого числа Jдосить широкий, щоб охопити всі обгрунтування цієї форми, що знаходяться поблизу pi.
Тім Пітерс,

2
І ось чому я люблю , якщо «бінарні» тригонометричні функції були більш широко реалізовані. Оскільки pi ніколи не можна представити раціонально, було б зручно з набором функцій, що працюють під кутами від 0 до 1.
труба

Ну, вони імпортували np.pi, ні math.pi.
EKons

2
@ Έρικ Κωνσταντόπουλος math.pi, np.piі scipy.piвсе ж; вони дублюються лише для зручності іменування; stackoverflow.com/questions/12645547/…
Тім Пітерс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.