為什么浮點數(shù)精度會丟失
浮點十進制值通常沒有完全相同的二進制表示形式。 這是 CPU 所采用的浮點數(shù)據(jù)表示形式的副作用。 為此,可能會經(jīng)歷一些精度丟失,并且一些浮點運算可能會產(chǎn)生意外的結(jié)果。
導(dǎo)致此行為的原因是下面之一:
十進制數(shù)的二進制表示形式可能不精確。
使用的數(shù)字之間類型不匹配(例如,混合使用浮點型和雙精度型)。
解決方案
如果你通讀了上面的為什么就會知道,這是IEEE 754標準中二進制浮點數(shù)的缺陷,沒有解決方案。
處理方案
-
高精度要求
使用系統(tǒng)提供的NSDecimalNumber API進行計算,最后轉(zhuǎn)換為字符串輸出顯示。NSDecimalNumber轉(zhuǎn)換方法:
#import "NSDecimalNumber+Y_Add.h"
@implementation NSDecimalNumber (Y_Add)
+ (NSDecimalNumber *)y_decimalNumberWithFloat:(float)value{
return [self y_decimalNumberWithFloat:value scale:2];
}
+ (NSDecimalNumber *)y_decimalNumberWithFloat:(float)value scale:(short)scale{
return [self y_decimalNumberWithFloat:value roundingMode:NSRoundBankers scale:scale];
}
+ (NSDecimalNumber *)y_decimalNumberWithFloat:(float)value roundingMode:(NSRoundingMode)roundingMode scale:(short)scale{
return [[[NSDecimalNumber alloc] initWithFloat:value] y_decimalNumberHandlerWithRoundingMode:roundingMode scale:scale];
}
+ (NSDecimalNumber *)y_decimalNumberWithDouble:(double)value{
return [self y_decimalNumberWithDouble:value scale:2];
}
+ (NSDecimalNumber *)y_decimalNumberWithDouble:(double)value scale:(short)scale{
return [self y_decimalNumberWithDouble:value roundingMode:NSRoundBankers scale:scale];
}
+ (NSDecimalNumber *)y_decimalNumberWithDouble:(double)value roundingMode:(NSRoundingMode)roundingMode scale:(short)scale{
return [[[NSDecimalNumber alloc] initWithFloat:value] y_decimalNumberHandlerWithRoundingMode:roundingMode scale:scale];
}
/**
* <#Description#>
*
* @return <#return value description#>
*/
- (NSDecimalNumber *)y_decimalNumberHandler{
return [self y_decimalNumberHandlerWithRoundingMode:NSRoundBankers scale:2];
}
- (NSDecimalNumber *)y_decimalNumberHandlerWithRoundingMode:(NSRoundingMode)roundingMode scale:(short)scale{
NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:roundingMode
scale:scale
raiseOnExactness:NO
raiseOnOverflow:YES
raiseOnUnderflow:YES
raiseOnDivideByZero:YES];
return [self decimalNumberByRoundingAccordingToBehavior:handler];
}
@end
-
普通精度要求
使用系統(tǒng)提供的數(shù)學運算進行計算,最后轉(zhuǎn)換為字符串輸出顯示。保留小數(shù)點后N位的方法:
/**
* formatterNumber .00 小數(shù)點后兩位
*
* @param number <#number description#>
*
* @return <#return value description#>
*/
+ (NSString *)y_formatterNumber:(NSNumber *)number{
return [self y_formatterNumber:number fractionDigits:2];
}
+ (NSString *)y_formatterNumber:(NSNumber *)number fractionDigits:(NSUInteger)fractionDigits{
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setMaximumFractionDigits:fractionDigits];
[numberFormatter setMinimumFractionDigits:fractionDigits];
return [numberFormatter stringFromNumber:number];
}