2012-08-23 41 views
3

我有兩個NSDecimalNumbers,我需要申請一個到另一個,原來這段代碼的權力,用雙打,我可以計算這個,像這樣的POW()函數的功率:NSDecimalNumber到NSDecimalNumber

double result = pow(value1, value2); 

我遇到的問題是我將代碼轉換爲使用NSDecimalNumbers,雖然它們包含方法toThePowerOf,它只接受int值。目前唯一的解決辦法是暫時轉換NSDecimalNumbers,但這會導致精度下降。

double value1 = [decimal1 doubleValue]; 
double value2 = [decimal2 doubleValue]; 

double result = pow(value1, value2); 
NSDecimalNumber *decimalResult = [[NSDecimalNumber alloc] initWithDouble:result]; 

有沒有辦法我可以用NSDecimalNumbers做這個計算,而不會失去精度?

我需要這與非整數值的工作,例如:

value1 = 1.06 
value2 = 0.0277777777 
+2

'value2'的範圍是否受到任何限制? – dasblinkenlight

回答

4

喬指出,如果你想爲正整數的力量做到這一點,你可以使用一個NSDecimal NSDecimalPower()結構源自您的NSDecimalNumber(我個人更喜歡使用這個結構,對於performance reasons)。

對於使用負整數和小數值的更一般情況,我有一些代碼是從Dave DeLong的DDMathParser庫中修改的。他已經刪除了該庫的NSDecimal部分,但是您可以找到the last commit for this support。我伸出Dave的指數支持分爲以下幾個功能:

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; 
} 

這個運行在正整數的權力,負整數權力,直接映射到根部分數冪精確的計算。儘管如此,它仍然落後於不能幹淨地落入其中一個分箱的分數冪的浮點計算。

不幸的是,這需要他的其他支持功能的一些工作。因此,我上傳了他的_DDDecimalFunctions.h_DDDecimalFunctions.m的增強版本,以提供此功能。它們還包括NSDecimal三角函數,對數和其他一些函數。目前在切線實施方面存在一些問題趨同,這就是爲什麼我還沒有完成關於此的公開帖子。

+0

所以這使用pow如果它是分數?我有的問題是我不想使用戰俘,我知道我的號碼將是真實的數字。對不起,我可能在開始的這個問題上一直沒有看到。 –

+0

@RobGill - 對於偶數分數(1/3,1/4),它可以將這些簡化爲精確的根,並保持精確度。 'pow()'是不映射到根或反向的情況下的回退,如2 ^(1.05)。我沒有意識到任何其他NSDecimal/NSDecimalNumber指數的實現比這更精確,這就是爲什麼我建立在Dave最初實現這個的基礎上。如果你能找到這樣的功能,請讓我知道,因爲我可以自己使用它。 –

1

我最近遇到同樣的問題,並開發了我自己的功能來做到這一點。該函數有,只要它得到一個真正的答案將計算任何基礎,任何權力,如果它決定了一個真正的答案無法計算它返回NSDecimalnumber.notANumber

我已經發布我的解決方案作爲一個問題的答案我張貼這樣同樣的問題here是鏈接。