非原创-搬运记录文章-浮点数的转化遇到的坑
由于计算机表示小数(包括float和double型小数)都有误差,我们不能直接用等号(==)判断两个小数是否相等。如何两个小数的差的绝对值很小,比如小于 0.0000001,就可以认为它们相等。
给出除了一个小数比较的方法:
bool (double num1, double num2) {
if ((num1 - num2 > -0.0000001) && (num1 - num2) < 0.0000001)
return true;
else
return false;
}
iOS Objective-c 中将NSString、NSNumber转化成CGFloat会有精度丢失;
网络传输中,JSON解析数字一般是NSNumber类型,在转化成CGFloat就会造成误差,网络传输数字最好是转成字符串类型。
OC小数转化
在OC中是否也有这样的问题,于是乎我测试下,因为考虑到iOS开发时,显示的小数一般不会超过4位:
CGFloat a = 66.6;
CGFloat b = 66.66;
CGFloat c = 66.666;
CGFloat d = 66.6666;
// CGFloat 转化成 NSNumber(一般会放进NSArray, NSDictionary中)
NSNumber *an = [NSNumber numberWithFloat:a];
NSNumber *bn = [NSNumber numberWithFloat:b];
NSNumber *cn = [NSNumber numberWithFloat:c];
NSNumber *dn = [NSNumber numberWithFloat:d];
// NSNumber floatValue 转化
float af = [an floatValue];
float bf = [bn floatValue];
float cf = [cn floatValue];
float df = [dn floatValue];
// NSNumber doubleValue 转化
double ab = [an doubleValue];
double bb = [bn doubleValue];
double cb = [cn doubleValue];
double db = [dn doubleValue];
// CGFloat 转化成 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 转化
float asf =[as floatValue];
float bsf =[bs floatValue];
float csf =[cs floatValue];
float dsf =[ds floatValue];
// NSString doubleValue 转化
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 转化下来的小数是比较准确的。
JSON小数转化
App应用一般数据都是从接口传来的
测一测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);
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
最后
聪明的你应该看出:
- NSNumber NSString 尽量用 doubleValue 来转化, 千万不能用 floatValue。
- 劝后台的同事把请求返回的数据全部设置为 String 类型。
- 如果涉及到精确计算的问题,请用 NSDecimalNumber 对象了参考。
网友评论