為什么浮點(diǎn)數(shù)精度會丟失
浮點(diǎn)十進(jìn)制值通常沒有完全相同的二進(jìn)制表示形式它掂。 這是 CPU 所采用的浮點(diǎn)數(shù)據(jù)表示形式的副作用棺弊。 為此,可能會經(jīng)歷一些精度丟失鱼喉,并且一些浮點(diǎn)運(yùn)算可能會產(chǎn)生意外的結(jié)果秀鞭。
導(dǎo)致此行為的原因是下面之一:
十進(jìn)制數(shù)的二進(jìn)制表示形式可能不精確。
使用的數(shù)字之間類型不匹配(例如扛禽,混合使用浮點(diǎn)型和雙精度型)锋边。
解決方案
如果你通讀了上面的為什么就會知道编曼,這是IEEE 754標(biāo)準(zhǔn)中二進(jìn)制浮點(diǎn)數(shù)的缺陷,沒有解決方案豆巨。
處理方案
-
高精度要求
使用系統(tǒng)提供的NSDecimalNumber API進(jìn)行計(jì)算,最后轉(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ù)學(xué)運(yùn)算進(jìn)行計(jì)算往扔,最后轉(zhuǎn)換為字符串輸出顯示。保留小數(shù)點(diǎn)后N位的方法:
/**
* formatterNumber .00 小數(shù)點(diǎn)后兩位
*
* @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];
}