Невероятный math.pow
Jul. 28th, 2012 10:27 pmЗадачка для младших инженеров-программистов электронно-вычислительных машин.
C:
#include <math.h>
#include <stdio.h>
int main()
{
printf("%d\n", (pow(43, 10) == 21611482313284249ll));
return 0;
}
Python:
import math
print(math.pow(43, 10) == 21611482313284249)
Вопрос: что выведется и почему?
no subject
Date: 2012-07-29 12:59 am (UTC)С другой стороны, на перле 43**10 вычисляется точно. И таки кто из них горбатый?
Upd: инструкцию и здесь надо читать, особенно редко применяемые места. Если не вспоминать про bignum и т.п. — то горб вполне есть, просто он на ещё больших числах. Что вполне в духе, да.
no subject
Date: 2012-07-29 06:21 am (UTC)А тут даже константу написать - надо как минимум лезть в мануал по каждому из языков.
И сравнивать плавающие операцией == - ну вааащщщщщще.
В моей личной практике была отладка кода, в котором накапливающаяся ошибка округления в тупо написанном алгоритме с double float давала в сочетании с вычитанием больших чисел эффект "0=1" на всего лишь сотне поступивших в программу результатов измерения.
no subject
Date: 2012-07-29 06:53 am (UTC)Пишущие на JavaScript, AWK, Lua, ... только так и сравнивают :)
Сравнивать с точностью до MY_EPSION?.. Сорри, что бы сравнить 43**10 и math.pow(43, 10) EPSILON должен быть не меньше чем 1.0 :)
no subject
Date: 2012-07-29 07:10 am (UTC)В Питоне
43**10тоже вычисляется точно. И даже43**100.no subject
Date: 2012-07-29 07:19 am (UTC)У этой истории есть и мораль — не используйте плавучку в криптографии.
no subject
Date: 2012-07-29 08:57 am (UTC)Как вы думаете, когда будет следующий True? :-)
... В двадцать первом веке, в самом начале ...
no subject
Date: 2012-07-29 09:00 am (UTC)... Sing, Maglor the Stranger, a ballade for me ...
no subject
Date: 2012-07-29 09:08 am (UTC)>>> N = 1000000000000000000
>>> [x for x in xrange(N, N + 1000) if x == float(x)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: long int too large to convert to int
И они это называют языком высокого уровня? Срочно линяем отсюда куда-нибудь!
1> N = 1000000000000000000.
1000000000000000000
2> [X || X <- lists:seq(N, N + 1000), X == float(X)].
[1000000000000000000,1000000000000000128,
1000000000000000256,1000000000000000384,1000000000000000512,
1000000000000000640,1000000000000000768,1000000000000000896]
Ага, сравнение длинных с плавающими в эрланге и питоне устроено одинаково. :-)
... Целуются обычно так - берётся девушка красивая ...
no subject
Date: 2012-07-29 10:36 am (UTC)no subject
Date: 2012-07-29 10:39 am (UTC)>>> N = 1000000000000000000
>>> [x for x in range(N, N + 1000) if x == float(x)]
[1000000000000000000, 1000000000000000128, 1000000000000000256, 1000000000000000384, 1000000000000000512, 1000000000000000640, 1000000000000000768, 1000000000000000896]
no subject
Date: 2012-07-29 10:48 am (UTC)no subject
Date: 2012-07-29 02:05 pm (UTC)>>> print pow(43, 10) == 43**10
True
>>> from math import pow
>>> pow(43, 10) == 43**10
False
no subject
Date: 2013-09-11 03:57 pm (UTC)таким образом в первой строке вывод будет 0 или 1, а во второй True или False
про формат чисел LL мне неизвестно. С требует явного указания типа здесь, т.к. оригинальный С long long int не имеет.
no subject
Date: 2013-09-11 05:59 pm (UTC)no subject
Date: 2013-09-11 06:21 pm (UTC)вы путаете стандарт языка и реализацию компилятора. вто время как вопрос был о том что выведется, а не как должно быть написано.
про ll я не помню. увы. что-то из виндовс. точнее в с99 не надо ll : 6.4.4.1 (http://www.open-std.org/jtc1/sc22/wg14/www/docs/C99RationaleV5.10.pdf)Unsuffixed integer constants may have different types in C99 than in C89. Such
10 constants greater than LONG_MAX are of type unsigned long in C89, but are of
type long long in C99 (if long long has more range than long).
тоесть implicitly.
про явное указание типа: оно должно быть указано везде в вышеприведенном C, в частности %d заберет со стека int, в то время как FALSE или TRUE могут быть определены как 0L и 1L (литры наверно?)
а питон печатает boolean.
вопрос с вычислениями (pow) в части C целиком зависит от реализации компилятора, в частности есть ли в BSP операции c longlong int (== например), какие они, как их использует компилятор при компиляции (а ведь может) и тп. то есть на него нету ответа. по кр мере стандарт языка здесь не помжет.
no subject
Date: 2013-10-03 05:45 pm (UTC)> вы путаете стандарт языка и реализацию компилятора.
Обычно компиляторы стараются реализовать стандарт. Отклонения считаются багами (или фичами).
> вто время как вопрос был о том что выведется, а не как должно быть написано.
Да, разумеется, результат платформозависим. Поэтому требовалось подумать, почему получен такой ответ. Угадать-то его с 50% вероятностью дело нехитрое.
> точнее в с99 не надо ll : 6.4.4.1
Вот этого я не знал. Да, это хорошо, это правильно.
> FALSE или TRUE могут быть определены как 0L и 1L
При чём здесь какие-то FALSE и TRUE? Они даже не упоминаются в коде.
> вопрос с вычислениями (pow) в части C целиком зависит от реализации компилятора
Да, это платформозависимый вопрос. Ответ на него зависит от числа разрядов мантиссы в double. Но практически на всех используемых сейчас платформах он однозначен.
no subject
Date: 2013-10-03 08:45 pm (UTC)да. ну так вот - предположим, питон собирается на той же платформе с той же libm (math) то есть берет ту же pow из C. поэтому если оба этих два примера на одной и той же платформе в части pow вернут одно и то же (почти, см. тут (http://stackoverflow.com/a/5246964/933849)), то нас может волновать только как работает в них сравнение '==' в отношении длинных лонгов на этой платформе... ну и далее в том же духе. то есть при всех спокойных (обычных) обстоятельствах результат вычисления стремится быть одинаков для этих двух примеров.
ну и разумаеется печатать они будут разные байты - питон свой буул а С напечатает int.
"При чём здесь какие-то FALSE и TRUE? Они даже не упоминаются в коде."
а при том, что это результат операции сравнения '==', в данном случае с константой.