【问题标题】:speed up this Standard Deviation method加快这种标准差方法
【发布时间】:2012-06-14 05:15:45
【问题描述】:

我有这个方法来计算一个 NSNumber 整数数组的标准偏差,给定一个平均值。计算使用 NSDecimals 来保留最高分辨率。这目前需要许多 cpu 周期,在保持所需分辨率的同时加快速度的任何帮助表示赞赏!谢谢。

-(NSDecimal)standardDeviationOf:(NSMutableArray *)array withMean:(NSDecimal)mean {

if (![array count]) return CPTDecimalFromInt(0);

NSDecimal sumOfSquaredDifferences = CPTDecimalFromInt(0);


for (NSNumber *number in array) {

    NSDecimal valueOfNumber = CPTDecimalFromInt([number intValue]);
    NSDecimal difference = CPTDecimalSubtract(valueOfNumber, mean);
    sumOfSquaredDifferences = CPTDecimalAdd(sumOfSquaredDifferences, CPTDecimalMultiply(difference, difference));

}

return CPTDecimalFromDouble(
                            sqrt(
                                 CPTDecimalDoubleValue(sumOfSquaredDifferences) / [[NSNumber numberWithInt:[array count]] doubleValue]
                                 )
                            );
}

【问题讨论】:

  • 您是否使用 Instruments 对您的代码进行了分析,以了解减速在哪里?我的猜测是您在intValueNSDecimal 之间进行的所有转换。将NSDecimalNumber 用于内部循环并使用NSDecimalNumber difference = [valueOfNumber decimalNumberBySubtracting:mean]; 会更好吗? (您需要先将一些内容从 NSDecimal 转换为 NSDecimalNumber。)
  • 既然您最终转换为double 来执行平方根,那么您是否真的通过使用NSDecimal 而不仅仅是double 进行所有循环算术来获得任何精度?
  • 不要使用 NSDecimal,只使用浮点数或双精度数。十进制算术的要点是具有精确的以 10 为底的十进制数字,主要用于金融交易。对于像您这样的应用程序来说,没有比这更准确的方法了。
  • 90% 的时间花在这两行: NSDecimal valueOfNumber = CPTDecimalFromInt([number intValue]); sumOfSquaredDifferences = CPTDecimalAdd(sumOfSquaredDifferences, CPTDecimalMultiply(difference, difference));

标签: objective-c c nsdecimalnumber standard-deviation


【解决方案1】:

NSDecimal 具有 38 位精度,而 double 具有大约 16 位精度。但是在循环结束时,当您将 sumOfSquaredDifferences 转换为 double 以用于 sqrt 函数时,您在 NSDecimal 中拥有的所有额外精度都“丢失”了。您不妨使用double 执行内部循环的算术运算,这应该比NSDecimal 快得多:

double sumOfSquaredDifferences = 0;
double valueOfMean = [mean doubleValue];
for (NSNumber *number in array) {

    double valueOfNumber = [number intValue];
    double difference = valueOfNumber - valueOfMean;
    sumOfSquaredDifferences += difference * difference;

}

return CPTDecimalFromDouble(sqrt(sumOfSquaredDifferences /
                                 double([array count])));

【讨论】:

  • 我也想做十进制的平方根,但不知道任何方法。您是正确的,这种方式会丢失精度。
  • 通过快速的网络搜索,我找到了这篇关于计算平方根和 NSDecimalNumber 的博文:cocoawithlove.com/2008/05/square-root-numerical-fun-with.html
  • 如果你从一堆 32 位整数计算标准差,而 32 位整数只有大约 10 位小数的精度,为什么你需要在NSDecimal?这没有意义。你不妨在 double 中做所有的算术运算,并在完成后转换为 NSDecimal。
猜你喜欢
  • 1970-01-01
  • 2014-08-13
  • 2020-01-03
  • 1970-01-01
  • 2013-12-17
  • 2013-05-21
  • 1970-01-01
  • 2013-10-22
  • 1970-01-01
相关资源
最近更新 更多