iOS浮點數(shù)精度丟失問題及處理方案

為什么浮點數(shù)精度會丟失

浮點十進制值通常沒有完全相同的二進制表示形式。 這是 CPU 所采用的浮點數(shù)據(jù)表示形式的副作用。 為此,可能會經(jīng)歷一些精度丟失,并且一些浮點運算可能會產(chǎn)生意外的結(jié)果。

導(dǎo)致此行為的原因是下面之一:
十進制數(shù)的二進制表示形式可能不精確。
使用的數(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];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容