我需要转换在double中执行的计算结果,但我不能使用decimalNumberByMultiplyingBy或任何其他NSDecimalNumber函数.我试图通过以下方式获得准确的结果: double calc1 = 23.5 * 45.6 * 52.7; // -- Correct answer
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; }