非原創(chuàng)-搬運(yùn)記錄文章-浮點(diǎn)數(shù)的轉(zhuǎn)化遇到的坑
由于計(jì)算機(jī)表示小數(shù)(包括float和double型小數(shù))都有誤差强霎,我們不能直接用等號(==)判斷兩個(gè)小數(shù)是否相等召嘶。如何兩個(gè)小數(shù)的差的絕對值很小,比如小于 0.0000001陡舅,就可以認(rèn)為它們相等。
給出除了一個(gè)小數(shù)比較的方法:
bool (double num1, double num2) {
if ((num1 - num2 > -0.0000001) && (num1 - num2) < 0.0000001)
return true;
else
return false;
}
iOS Objective-c 中將NSString、NSNumber轉(zhuǎn)化成CGFloat會有精度丟失摆寄;
網(wǎng)絡(luò)傳輸中,JSON解析數(shù)字一般是NSNumber類型坯门,在轉(zhuǎn)化成CGFloat就會造成誤差微饥,網(wǎng)絡(luò)傳輸數(shù)字最好是轉(zhuǎn)成字符串類型。
OC小數(shù)轉(zhuǎn)化
在OC中是否也有這樣的問題古戴,于是乎我測試下欠橘,因?yàn)榭紤]到iOS開發(fā)時(shí),顯示的小數(shù)一般不會超過4位:
CGFloat a = 66.6;
CGFloat b = 66.66;
CGFloat c = 66.666;
CGFloat d = 66.6666;
// CGFloat 轉(zhuǎn)化成 NSNumber(一般會放進(jìn)NSArray, NSDictionary中)
NSNumber *an = [NSNumber numberWithFloat:a];
NSNumber *bn = [NSNumber numberWithFloat:b];
NSNumber *cn = [NSNumber numberWithFloat:c];
NSNumber *dn = [NSNumber numberWithFloat:d];
// NSNumber floatValue 轉(zhuǎn)化
float af = [an floatValue];
float bf = [bn floatValue];
float cf = [cn floatValue];
float df = [dn floatValue];
// NSNumber doubleValue 轉(zhuǎn)化
double ab = [an doubleValue];
double bb = [bn doubleValue];
double cb = [cn doubleValue];
double db = [dn doubleValue];
// CGFloat 轉(zhuǎn)化成 NSString
NSString *as = [NSString stringWithFormat:@"%f", a];
NSString *bs = [NSString stringWithFormat:@"%f", b];
NSString *cs = [NSString stringWithFormat:@"%f", c];
NSString *ds = [NSString stringWithFormat:@"%f", d];
// NSString floatValue 轉(zhuǎn)化
float asf =[as floatValue];
float bsf =[bs floatValue];
float csf =[cs floatValue];
float dsf =[ds floatValue];
// NSString doubleValue 轉(zhuǎn)化
double asb = [as doubleValue];
double bsb = [bs doubleValue];
double csb = [cs doubleValue];
double dsb = [ds doubleValue];
打印信息:
== CGFloat 打印
a: 66.600000
b: 66.660000
c: 66.666000
d: 66.666600
== NSNumber 打印
an: 66.6
bn: 66.66
cn: 66.666
dn: 66.6666
== NSNumber floatValue 打印
af: 66.599998
bf: 66.660004
cf: 66.666000
df: 66.666603
== NSNumber doubleValue 打印
ab: 66.599998
bb: 66.660004
cb: 66.666000
db: 66.666603
== NSString 打印
as: 66.600000
bs: 66.660000
cs: 66.666000
ds: 66.666600
== NSString floatValue 打印
asf: 66.599998
bsf: 66.660004
csf: 66.666000
dsf: 66.666603
== NSString doubleValue 打印
asb: 66.600000
bsb: 66.660000
csb: 66.666000
dsb: 66.666600
NSString doubleValue 轉(zhuǎn)化下來的小數(shù)是比較準(zhǔn)確的现恼。
JSON小數(shù)轉(zhuǎn)化
App應(yīng)用一般數(shù)據(jù)都是從接口傳來的
測一測JSON傳數(shù)字:
NSString *json = @"{"a":66.6, "b":66.66, "c":66.666, "d":66.6666}";
NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"%@", dict);
for (NSString *key in [dict allKeys]) {
id object = [dict objectForKey:key];
NSLog(@"%@: %@ - %@", key, [object class], object);
float xf = [object floatValue];
double yf = [object doubleValue];
printf("nf: %f - df: %fn", xf, yf);
}
打印信息:
{
a = "66.59999999999999";
b = "66.66";
c = "66.666";
d = "66.6666";
}
d: __NSCFNumber - 66.6666
nf: 66.666603 - df: 66.666600
b: __NSCFNumber - 66.66
nf: 66.660004 - df: 66.660000
c: __NSCFNumber - 66.666
nf: 66.666000 - df: 66.666000
a: __NSCFNumber - 66.59999999999999
nf: 66.599998 - df: 66.600000
JSON傳字符串:
NSString *json = @"{"a":"66.6","b":"66.66","c":"66.666","d":"66.6666"}";
NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"dict: %@", dict);
for (NSString *key in [dict allKeys]) {
id object = [dict objectForKey:key];
NSLog(@"%@: %@ - %@", key, [object class], object);
float xf = [object floatValue];
double yf = [object doubleValue];
printf("nf: %f - df: %fn", xf, yf);
}
輸出信息:
{
a = "66.6";
b = "66.66";
c = "66.666";
d = "66.6666";
}
d: NSTaggedPointerString - 66.6666
nf: 66.666603 - df: 66.666600
b: NSTaggedPointerString - 66.66
nf: 66.660004 - df: 66.660000
c: NSTaggedPointerString - 66.666
nf: 66.666000 - df: 66.666000
a: NSTaggedPointerString - 66.6
nf: 66.599998 - df: 66.600000
最后
聰明的你應(yīng)該看出:
- NSNumber NSString 盡量用 doubleValue 來轉(zhuǎn)化肃续, 千萬不能用 floatValue黍檩。
- 勸后臺的同事把請求返回的數(shù)據(jù)全部設(shè)置為 String 類型。
- 如果涉及到精確計(jì)算的問題始锚,請用 NSDecimalNumber 對象了參考刽酱。
參考
iOS浮點(diǎn)數(shù)的轉(zhuǎn)化遇到的坑
iOS開發(fā)可能遇到的坑——浮點(diǎn)數(shù)的轉(zhuǎn)化顯示問題