Objective C Pow функция смешанной точности результат
Общий вопрос о функции pow в target-c.
Почему следующий код выплевывает ans=4.9999999, когда base = 125
NSDecimalNumber * base = [[NSDecimalNumber alloc ]initWithString:@"125"];
NSDecimalNumber * root = [[NSDecimalNumber alloc] initWithString:@"3"];
double ans=pow(125, 1.0/[root doubleValue]);
и ровно 3, когда база = 27
NSDecimalNumber * base = [[NSDecimalNumber alloc ]initWithString:@"27"];
NSDecimalNumber * root = [[NSDecimalNumber alloc] initWithString:@"3"];
double ans=pow(125, 1.0/[root doubleValue]);
1 ответ
Здесь есть несколько факторов. Самое главное, 1.0/3.0
не совсем одна треть, так что вы не вычисляете кубический корень base
, Вместо этого вычисление, которое вы указали:
base**0.333333333333333314829616256247390992939472198486328125
или же
exp(0.333333333333333314829616256247390992939472198486328125 * log(base))
когда base
является 125
, точный результат действительного числа этого вычисления:
4.999999999999999553291243227753830961690873860134487744...
Два ближайших представимых двойника к этому значению 5.0
а также:
4.99999999999999911182158029987476766109466552734375
Последнее значение чуть ближе к математически точному результату, поэтому pow
Функция вернула наилучший (или "правильно округленный") ответ.
Когда вы делаете то же самое вычисление с base
равный 27, математически точный результат действительного числа:
2.99999999999999981704430129767885583952101310176125736...
В этом случае это число несколько ближе к 3.0
чем для любого другого представимого двойника, так что опять pow
вернул наилучший возможный результат.
Так что в этих случаях pow
Функция дает вам наиболее точные возможные результаты для вычислений, которые вы ему предложили. Теперь, что сказал, нет никакой гарантии, что pow
делает это для всех возможных входов (и вообще, вообще-то, нет). Вы не получите такие точные результаты для всех входных данных, и вы получите значительно менее точные результаты для многих входных данных на некоторых платформах. В общем, вы не должны зависеть от последнего бита округления pow
функция или любая функция, которая явно не определена для получения правильно округленных результатов.
Короче говоря, полученные вами результаты являются наилучшими из возможных, а на некоторых других платформах вам не повезет.
Альтернативы:
Вы можете рассмотреть возможность использования
cbrt
функция, которая также не гарантирует правильного округления, но, по крайней мере, вычисляет корень куба, а не 0,3333333333333333148296...th степень.Если вы априори знаете, что результатом должно быть целое число, вы можете округлить его до ближайшего целого числа через
round
или жеrint
функция.Если вам действительно требуется точное округление последнего бита, рассмотрите возможность использования библиотеки CRLibm. Это приведет к некоторым затратам производительности, но если вам абсолютно необходимо иметь правильное округление, это единственный хороший вариант (но учтите, что он даст точно такие же результаты для этих конкретных примеров).