金額相關(guān)精度問(wèn)題

最近項(xiàng)目中遇到金額計(jì)算歌逢,CGFloat類(lèi)型金額計(jì)算的過(guò)程中祈餐,讓我吃了不少苦頭鹃操,先來(lái)看下面幾行代碼:

示例代碼

    CGFloat var1 = 120.66;
    CGFloat var2 = 120.66;
    
    CGFloat var3 = [@"120.66" floatValue];
    CGFloat var4 = [@"120.66" floatValue];
    
    CGFloat var5 = 120.67 - 0.01;
    
    CGFloat var6 = [@"120.67" floatValue] - 0.01;
    
    bool flag1 = var1 == var2;
    bool flag2 = var3 == var4;
    bool flag3 = var3 == var5;
    bool flag4 = var5 == var6;
    bool flag5 = var3 == var6;

略去猜答案的過(guò)程仓坞,直接看結(jié)果

圖一
圖一

現(xiàn)象總結(jié)

  • var1 和var2相等
  • var3 和var4相等
  • NSString 的 floatValue 會(huì)讓CGFloat 的精度增加
  • 精度確定的float類(lèi)型做運(yùn)算颜说,精度確定 var5 = 120.66
  • 不同精度的float類(lèi)型做運(yùn)算购岗,精度會(huì)丟失 var6 = 120.65999816894531

浮點(diǎn)數(shù)相等問(wèn)題

    CGFloat x = var5 - var6;  
    const CGFloat EPSINON = 0.000001;  
    if (( x >= -EPSINON ) && ( x <= EPSINON ))  
    {  
        NSLog("var5 和var6相等");  
    } 

鑒于CGFloat在處理金額過(guò)程中會(huì)遇到精度問(wèn)題,iOS中提供了NSDecimalNumber類(lèi)來(lái)處理精度問(wèn)題,如果要四舍五入的話還要使用另一個(gè)類(lèi) NSDecimalNumberHandler

NSDecimalNumber類(lèi)

/*
     講述下參數(shù)的含義:
     RoundingMode: 簡(jiǎn)單講就是你要四舍五入操作的標(biāo)準(zhǔn).
typedef NS_ENUM(NSUInteger, NSRoundingMode) {
    NSRoundPlain,   // 精度位后四舍五入
    NSRoundDown,    // 精度位后舍去
    NSRoundUp,      // 精度位后入上去
    NSRoundBankers  // 精度位后的數(shù)值等于5時(shí)门粪,分兩種情況:5后面還有其他數(shù)字(非0)喊积,則進(jìn)位后舍去;若5后面是0(即5是最后一位)玄妈,則根據(jù)5前一位數(shù)的奇偶性來(lái)判斷是否需要進(jìn)位乾吻,奇數(shù)進(jìn)位,偶數(shù)舍去措近。
};      
    // Rounding policies :
    // Original
    //    value 1.2  1.21  1.25  1.35  1.27
    // Plain    1.2  1.2   1.3   1.4   1.3
    // Down     1.2  1.2   1.2   1.3   1.2
    // Up       1.2  1.3   1.3   1.4   1.3
    // Bankers  1.2  1.2   1.2   1.4   1.3

     scale : 需要保留的精度溶弟。
     raiseOnExactness : 為YES時(shí)在處理精確時(shí)如果有錯(cuò)誤,就會(huì)拋出異常瞭郑。
     raiseOnOverflow  : YES時(shí)在計(jì)算精度向上溢出時(shí)會(huì)拋出異常辜御,否則返回。
     raiseOnUnderflow : YES時(shí)在計(jì)算精度向下溢出時(shí)會(huì)拋出異常屈张,否則返回.
     raiseOnDivideByZero : YES時(shí)擒权。當(dāng)除以0時(shí)會(huì)拋出異常袱巨,否則返回。
     */
     
     保留2位小數(shù)
NSDecimalNumberHandler *roundUp = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain
                                                                                            scale:2
                                                                                 raiseOnExactness:NO
                                                                                  raiseOnOverflow:NO
                                                                                 raiseOnUnderflow:NO
                                                                              raiseOnDivideByZero:YES];                                                                                                                                                 

計(jì)算金額并四舍五入

NSDecimalNumber *originMoney = [NSDecimalNumber decimalNumberWithString:num];//通過(guò)字符串計(jì)算金額
NSDecimalNumber *roundMoney = [subtotal decimalNumberByRoundingAccordingToBehavior:roundUp];//按照設(shè)定的規(guī)則計(jì)算出金額

金額計(jì)算實(shí)例

NSDecimalNumber *varDecimal1 = [NSDecimalNumber decimalNumberWithString:@"120.661"];//120.661
NSDecimalNumber *varDecimal2 = [NSDecimalNumber decimalNumberWithString:@"120.670"];//120.670

//加
[varDecimal1 decimalNumberByAdding:varDecimal2];

//減
NSDecimalNumber *varDecimal3 = [[varDecimal2 decimalNumberBySubtracting:varDecimal1] decimalNumberByRoundingAccordingToBehavior:roundUp];//0.01

//乘
[varDecimal1 decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"0.005"]];

//除
[varDecimal1 decimalNumberByDividingBy:varDecimal2];

//比較
[varDecimal1 compare:varDecimal2] == NSOrderedAscending //varDecimal1小于varDecimal2

總結(jié)

  1. 金額相關(guān)碳抄,后臺(tái)要傳字符串到前臺(tái)
  2. 計(jì)算過(guò)程中要用NSDecimalNumber來(lái)防止計(jì)算過(guò)程中出現(xiàn)精度錯(cuò)誤
  3. [@"120.67" floatValue] - 0.01 不等于120.66
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末愉老,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子剖效,更是在濱河造成了極大的恐慌嫉入,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件璧尸,死亡現(xiàn)場(chǎng)離奇詭異咒林,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)爷光,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)垫竞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蛀序,你說(shuō)我怎么就攤上這事欢瞪。” “怎么了徐裸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵遣鼓,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我倦逐,道長(zhǎng)譬正,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任檬姥,我火速辦了婚禮曾我,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘健民。我一直安慰自己抒巢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布秉犹。 她就那樣靜靜地躺著蛉谜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪崇堵。 梳的紋絲不亂的頭發(fā)上型诚,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音鸳劳,去河邊找鬼狰贯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的涵紊。 我是一名探鬼主播傍妒,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼摸柄!你這毒婦竟也來(lái)了颤练?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驱负,失蹤者是張志新(化名)和其女友劉穎嗦玖,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體跃脊,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡踏揣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匾乓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡又谋,死狀恐怖拼缝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情彰亥,我是刑警寧澤咧七,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站任斋,受9級(jí)特大地震影響继阻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜废酷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一瘟檩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧澈蟆,春花似錦墨辛、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至寥闪,卻和暖如春太惠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疲憋。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工凿渊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓嗽元,卻偏偏與公主長(zhǎng)得像敛纲,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子剂癌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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