Ios pow功能是如何工作的?
我想写我自己的幂函数来处理不是整数的小数和指数。我第一次尝试结合使用牛顿法和内置整数幂法,但由于牛顿法,当指数超过2位小数时,我会出现溢出错误。所以我想也许浮点值pow函数可以作为我自己函数的一个很好的模型。所以我想知道是否有人知道我在哪里可以找到一些关于pow函数内部工作原理的文档 编辑:Ios pow功能是如何工作的?,ios,objective-c,c,Ios,Objective C,C,我想写我自己的幂函数来处理不是整数的小数和指数。我第一次尝试结合使用牛顿法和内置整数幂法,但由于牛顿法,当指数超过2位小数时,我会出现溢出错误。所以我想也许浮点值pow函数可以作为我自己函数的一个很好的模型。所以我想知道是否有人知道我在哪里可以找到一些关于pow函数内部工作原理的文档 编辑: @wombat57,这些链接看起来可能就是我要找的,但我不知道该怎么读。你建议的算法实际上就是我正在使用的。由于指数非常大,溢出来自牛顿方法。因为我得到的是十进制的指数,所以我必须先把它转换成分数。就我所知
@wombat57,这些链接看起来可能就是我要找的,但我不知道该怎么读。你建议的算法实际上就是我正在使用的。由于指数非常大,溢出来自牛顿方法。因为我得到的是十进制的指数,所以我必须先把它转换成分数。就我所知,在代码中,唯一的方法是将十进制数乘以10,直到得到一个整数,然后用它作为分子。这样,对于小数位数为3或更多的数字,指数为100+。这会导致溢出错误。编辑1:以下是指向实际源的链接 我得到了这个问题的链接,这个问题有很多相关的讨论 此页面描述了一个算法:。 x^(1/n)=x的第n个根,x^mn=(x^m)^n。因此,x^(m/n)=(x的第n根)^m。可以用牛顿法计算任意根。整数幂可以通过平方求幂来计算。对于无理指数,可以使用越来越精确的有理近似,直到获得所需的有效位数 编辑2: 牛顿的方法包括将你目前的猜测提高到你试图找到的根的幂。如果该功率很大,并且猜测值甚至有点太高,则可能导致溢出。这里的一个解决方案是确定这种情况。如果发生溢出,这意味着猜测过高。您可以通过(每当猜测导致溢出时)将当前猜测设置为上一个没有溢出的猜测和当前猜测之间的值(您可能需要多次这样做)来解决此问题。也就是说,每当牛顿的方法溢出时,对没有溢出的最后一个猜测进行二进制搜索。下面是一些实现所有这些功能的python:
def nroot(n, b, sig_figs = 10):
g1 = 1.0
g2 = 1.0
while True:
done = False
while not done:
try:
g3 = g2 - ((g2**b) - n) / (b * (g2**(b-1)))
done = True
except OverflowError:
g2 = (g1 + g2) / 2.0
if abs(g2 - g3) < 1.0 / (10**sig_figs):
return g3
g1 = g2
g2 = g3
def npowbysqr(n, p):
if p == 0:
return 1.0
if p % 2 == 0:
v = npowbysqr(n, p/2)
return v*v
else:
return n*npowbysqr(n, p-1)
def npow(n, p):
return npowbysqr(nroot(n, 1000000), int(p*1000000))
print npow(5, 4.3467)
print 5**4.3467
def nroot(n,b,sig_图=10):
g1=1.0
g2=1.0
尽管如此:
完成=错误
虽然没有这样做:
尝试:
g3=g2-((g2**b)-n)/(b*(g2**(b-1)))
完成=正确
除溢出错误外:
g2=(g1+g2)/2.0
如果abs(g2-g3)<1.0/(10**sig_图):
返回g3
g1=g2
g2=g3
def npowbysqr(n,p):
如果p==0:
返回1.0
如果p%2==0:
v=npowbysqr(n,p/2)
返回v*v
其他:
返回n*npowbysqr(n,p-1)
def npow(n,p):
返回npowbysqr(nroot(n,1000000),int(p*1000000))
打印npow(5,4.3467)
打印5**4.3467
我应该补充一点,也许有更好的解决办法。这似乎是可行的,但是不久前我碰巧需要这样的东西。谢天谢地,戴夫·德隆在他的DDMathParser中一直在修补这一点,所以我就以此为基础进行了构建。他从他的代码中删除了他的实现,但我接受了并修改了它。这是我对他的十进制幂函数的理解:
extern NSDecimal DDDecimalPower(NSDecimal d, NSDecimal power) {
NSDecimal r = DDDecimalOne();
NSDecimal zero = DDDecimalZero();
NSComparisonResult compareToZero = NSDecimalCompare(&zero, &power);
if (compareToZero == NSOrderedSame) {
return r;
}
if (DDDecimalIsInteger(power))
{
if (compareToZero == NSOrderedAscending)
{
// we can only use the NSDecimal function for positive integers
NSUInteger p = DDUIntegerFromDecimal(power);
NSDecimalPower(&r, &d, p, NSRoundBankers);
}
else
{
// For negative integers, we can take the inverse of the positive root
NSUInteger p = DDUIntegerFromDecimal(power);
p = -p;
NSDecimalPower(&r, &d, p, NSRoundBankers);
r = DDDecimalInverse(r);
}
} else {
// Check whether this is the inverse of an integer
NSDecimal inversePower = DDDecimalInverse(power);
NSDecimalRound(&inversePower, &inversePower, 34, NSRoundBankers); // Round to 34 digits to deal with cases like 1/3
if (DDDecimalIsInteger(inversePower))
{
r = DDDecimalNthRoot(d, inversePower);
}
else
{
double base = DDDoubleFromDecimal(d);
double p = DDDoubleFromDecimal(power);
double result = pow(base, p);
r = DDDecimalFromDouble(result);
}
}
return r;
}
它试图找出常见的情况,并对这些情况进行更精确的计算。但是,对于不适合这些情况的事情,它确实依赖于pow()
我使用的其余NSDecimal函数都可以找到和找到。我已经找到了一个适合我需要的函数,并且有望满足许多其他人的需要。以下方法是完全注释的,适用于任何具有实值的幂函数。此方法还仅使用NSDEcimalNumber,这意味着您不会因为浮点舍入错误而失去任何精度。这个方法有两个参数,一个是基数,一个是幂,都是小数。这就是:
//these are constants that will be used
NSDecimalNumber *ten = [NSDecimalNumber decimalNumberWithString:@"10"];
NSDecimalNumber *one = NSDecimalNumber.one;
//these will together hold the power in fractional form
NSDecimalNumber *numerator = power, *denominator = one;
//this will hold the final answer and all previous guesses the first guess is set to be the base
NSDecimalNumber *powAns = base;
//this will hold the change in your guess, also serves as an idea of how large the error is
NSDecimalNumber *error = one;
//part1 holds f(x) and part2 holds f'(x)
NSDecimalNumber *part1, *part2;
//if the base is < 0 and the power is not whole, answer is not real
if ([base doubleValue] < 0 && [[power stringValue] rangeOfString:@"."].location != NSNotFound)
return NSDecimalNumber.notANumber;
//converts power to a fractional value
while ([[numerator stringValue] rangeOfString:@"."].location != NSNotFound) {
numerator = [numerator decimalNumberByMultiplyingBy:ten];
denominator = [denominator decimalNumberByMultiplyingBy:ten];
}
//conditions here are the precision you wish to get
while ([error compare:[NSDecimalNumber decimalNumberWithString:@"1e-20"]] == NSOrderedDescending ||
[error compare:[NSDecimalNumber decimalNumberWithString:@"-1e-20"]] == NSOrderedAscending) {
//if this catches an overflow error it is set to be a very large number otherwise the value cannot be a number, however no other error should be returned.
@try {
part1 = [powAns decimalNumberByRaisingToPower:[denominator intValue]];
}
@catch (NSException *exception) {
if ([exception.name isEqual: NSDecimalNumberOverflowException])
part1 = [NSDecimalNumber decimalNumberWithString:@"10e127"];
else
return NSDecimalNumber.notANumber;
}
part1 = [part1 decimalNumberBySubtracting:base];
//if this catches an overflow error it is set to be a very large number otherwise the value cannot be a number, however no other error should be returned.
@try {
part2 = [powAns decimalNumberByRaisingToPower:[denominator intValue]-1];
part2 = [part2 decimalNumberByMultiplyingBy:denominator];
}
@catch (NSException *exception) {
if ([exception.name isEqual: NSDecimalNumberOverflowException])
part2 = [NSDecimalNumber decimalNumberWithString:@"10e127"];
else
return NSDecimalNumber.notANumber;
}
//error is the change in the estimated value or y - f(x)/f'(x)
error = [part1 decimalNumberByDividingBy:part2];
powAns = [powAns decimalNumberBySubtracting: error];
}
//if the numerator value is negative it must be made positive and the answer is then inverted
if ([numerator intValue] < 0) {
powAns = [powAns decimalNumberByRaisingToPower:abs([numerator intValue])];
powAns = [one decimalNumberByDividingBy:powAns];
}
else
powAns = [powAns decimalNumberByRaisingToPower:[numerator intValue]];
return powAns;
//这些是将要使用的常量
NSDecimalNumber*ten=[NSDecimalNumber decimalnumberwhithstring:@“10”];
NSDecimalNumber*one=NSDecimalNumber.one;
//这些将以分数形式共同持有权力
N小数*分子=幂,*分母=一;
//这将保留最终答案和之前的所有猜测-第一个猜测被设置为基础
NSDecimalNumber*powAns=基数;
//这将保持你猜测的变化,也可以作为误差有多大的概念
NSDecimalNumber*错误=1;
//第1部分保持f(x),第2部分保持f'(x)
N小数*第1部分,*第2部分;
//如果基数<0且功率不完整,则答案不真实
如果([base doubleValue]<0&&[power stringValue]rangeOfString:@“)。位置!=NSNotFound)
返回NSDecimalNumber.notANumber;
//将幂转换为小数
while([[numerator stringValue]rangeOfString:@.”).location!=NSNotFound){
分子=[分子小数位数乘:十];
分母=[分母小数位数乘:十];
}
//这里的条件是您希望获得的精度
而([错误比较:[NSDecimalNumber decimalNumberWithString:@“1e-20”]]==取消搜索||
[错误比较:[NSDecimalNumber decimalNumberWithString:@“-1e-20”]==传感器解除设置){
//如果捕获到溢出错误,则将其设置为非常大的数字,否则该值不能为数字,但不应返回其他错误。
@试一试{
第1部分=[powAns decimalNumberByRaisingToPower:[分母intValue]];
}
@捕获(NSException*异常){
if([exception.name isEqual:NSDecimalNumberOverflowException])
第1部分=[NSDecimalNumber decimalNumberWithString:@“10e127”];
其他的
返回NSDecimalNumber.notANumber;
}
part1=[part1小数位数