pow(a,b)
часто считается, определяется и реализуется как exp(log(a)*b)
, где log(a)
- натуральный логарифм a.log (a) не определен для <= 0 в действительных числах.Поэтому вам нужно либо написать функцию с особым регистром для отрицательного а и целого числа <code>b и / или b=1/(some_integer)
.Для целого числа b
особый случай прост, но для b=1/(some_integer)
он склонен к проблемам округления, как указывал Свен Марнах.
Может быть, для вашего домена pow(-a,b)
всегда должно быть -pow(a,b)
?Но тогда вы просто реализуете такую функцию, поэтому я предполагаю, что вопрос требует большего объяснения.
Как и предполагал duskwuff, гораздо более надежное и «математическое» решение состоит в использовании сложных функций log и exp, но это намногоболее "сложный" (извините за каламбур), чем кажется на первый взгляд (хотя есть функция cpow
).И это будет намного медленнее, если вам придется вычислять много pow () s.
Теперь есть важный улов с комплексными числами, которые могут или не могут иметь отношение к вашей проблемной области: когда все сделано правильно,результат pow(a,b)
- это не одно, а часто несколько комплексных чисел , но в тех случаях, которые вас интересуют, одним из них будет комплексное число с почти нулевой мнимой частью (это будет не- ноль из-за ошибок округления), которые вы можете просто игнорировать и / или не вычислять в своем коде.
Чтобы продемонстрировать это, рассмотрите, что такое pow(-1,.5)
.Это число X
такое, что X^2==-1
.Угадай, что?Есть 2 таких числа: i
и -i
.Как правило, pow(-1, 1/N)
имеет ровно N
решений, хотя вас интересует только одно из них.
Если мнимая часть всех результатов pow(a,b)
значительна, это означает, что вы передаете неправильные значения,Для значений с плавающей запятой одинарной точности в диапазоне, который вы описываете, 1e-6 * max (abs (a), abs (b)) будет хорошей отправной точкой для определения «достаточно значительного» порога.Крайние «неправильные значения» будут pow(-1,0.5)
, которые будут возвращать 0 + 1i
(0
в реальной части, 1
в мнимой части).Здесь мнимая часть огромна относительно входной и реальной части, так что вы знаете, что испортили свои входные значения.
В любой разумной реализации с одним возвращаемым результатом cpow()
, cpow(-1,0.3333)
, вероятно, вернет что-то вроде -1+0.000001i
и проигнорирует два других значения со значительными мнимыми частями.Так что вы можете просто принять это реальное значение, и это ваш ответ.