为什么浮点数精度会丢失
浮点十进制值通常没有完全相同的二进制表示形式。 这是 CPU 所采用的浮点数据表示形式的副作用。 为此,可能会经历一些精度丢失,并且一些浮点运算可能会产生意外的结果。
导致此行为的原因是下面之一:
十进制数的二进制表示形式可能不精确。
使用的数字之间类型不匹配(例如,混合使用浮点型和双精度型)。
解决方案
如果你通读了上面的为什么就会知道,这是IEEE 754标准中二进制浮点数的缺陷,没有解决方案。
处理方案
-
高精度要求
使用系统提供的NSDecimalNumber API进行计算,最后转换为字符串输出显示。NSDecimalNumber转换方法:
#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
-
普通精度要求
使用系统提供的数学运算进行计算,最后转换为字符串输出显示。保留小数点后N位的方法:
/**
* formatterNumber .00 小数点后两位
*
* @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];
}
网友评论