首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSDecimalNumber到NSDecimalNumber的威力

NSDecimalNumber到NSDecimalNumber的威力
EN

Stack Overflow用户
提问于 2012-08-23 22:32:01
回答 2查看 1.3K关注 0票数 4

我有两个NSDecimalNumbers,我需要将一个应用到另一个的幂上,最初这段代码使用doubles,我可以像这样用pow()函数来计算:

代码语言:javascript
复制
double result = pow(value1, value2);

我遇到的问题是,我正在将代码转换为使用NSDecimalNumbers,虽然它们包含方法toThePowerOf,但它只接受int值。目前,我对这个问题的唯一解决方案是临时转换NSDecimalNumbers,但这会导致精度损失。

代码语言:javascript
复制
double value1 = [decimal1 doubleValue];
double value2 = [decimal2 doubleValue];

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

有没有一种方法可以让我用NSDecimalNumbers进行计算而不损失精度?

我需要它来处理非整数值,例如:

代码语言:javascript
复制
value1 = 1.06
value2 = 0.0277777777
EN

回答 2

Stack Overflow用户

发布于 2012-08-23 23:21:28

正如Joe指出的,如果您想对正整数幂执行此操作,则可以在从NSDecimalNumber派生的NSDecimal结构上使用NSDecimalPower() (我个人更喜欢使用performance reasons的结构)。

对于更一般的处理负整数和小数值的情况,我从Dave DeLong的DDMathParser库中修改了一些代码。他后来删除了这个库的NSDecimal部分,但您可以找到the last commit for this support。我将Dave的指数支持扩展为以下函数:

代码语言:javascript
复制
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三角函数、对数函数和其他一些函数。目前在切线实现上存在一些关于收敛的问题,这就是为什么我还没有完成一篇关于这方面的公共帖子。

票数 4
EN

Stack Overflow用户

发布于 2014-06-13 14:15:29

我最近遇到了同样的问题,并开发了我自己的函数来做这件事。函数has将计算任何幂的任何底,只要它产生一个实数答案,如果它确定一个实数答案不能计算,它将返回NSDecimalnumber.notANumber

我已经发布了我的解决方案,作为我发布的相同问题的答案,所以here是链接。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12094011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档