ios – 将double转换为NSDecimalNumber,同时保持准确性

我需要转换在double中执行的计算结果,但我不能使用decimalNumberByMultiplyingBy或任何其他NSDecimalNumber函数.我试图通过以下方式获得准确的结果:

double calc1 = 23.5 * 45.6 * 52.7;  // <-- Correct answer is 56473.32
NSLog(@"calc1 = %.20f",calc1);

– > calc1 = 56473.32000000000698491931

NSDecimalNumber *calcDN = (NSDecimalNumber *)[NSDecimalNumber numberWithDouble:calc1];
NSLog(@"calcDN = %@",[calcDN stringValue]);

– > calcDN = 56473.32000000001024

NSDecimalNumber *testDN = [[[NSDecimalNumber decimalNumberWithString:@"23.5"] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"45.6"]] decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"52.7"]];
NSLog(@"testDN = %@",[testDN stringValue]);

– > testDN = 56473.32

我知道这种差异与各自的准确性有关.

但这是我的问题:无论double的初始值是多少,我怎么能以最准确的方式舍入这个数字呢?如果存在更准确的方法来进行初始计算,那么该方法是什么?

解决方法

我建议根据双精度数字对数字进行舍入,以便截断NSDecimalNumber只显示相应的位数,从而消除潜在错误形成的数字,例如:

// Get the number of decimal digits in the double
int digits = [self countDigits:calc1];

// Round based on the number of decimal digits in the double
NSDecimalNumberHandler *behavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:digits raiSEOnExactness:NO raiSEOnOverflow:NO raiSEOnUnderflow:NO raiSEOnDivideByZero:NO];
NSDecimalNumber *calcDN = (NSDecimalNumber *)[NSDecimalNumber numberWithDouble:calc1];
calcDN = [calcDN decimalNumberByRoundingAccordingToBehavior:behavior];

我已经改编了this answer的countDigits:方法

- (int)countDigits:(double)num {
    int rv = 0;
    const double insignificantDigit = 18; // <-- since you want 18 significant digits
    double intpart,fracpart;
    fracpart = modf(num,&intpart); // <-- Breaks num into an integral and a fractional part.

    // While the fractional part is greater than 0.0000001f,// multiply it by 10 and count each iteration
    while ((fabs(fracpart) > 0.0000001f) && (rv < insignificantDigit)) {
        num *= 10;
        fracpart = modf(num,&intpart);
        rv++;
    }
    return rv;
}

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...