浮点数的转化遇到的坑

2021-03-11  本文已影响0人  特拉法尔咖

非原创-搬运记录文章-浮点数的转化遇到的坑

由于计算机表示小数(包括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

最后

聪明的你应该看出:

  1. NSNumber NSString 尽量用 doubleValue 来转化, 千万不能用 floatValue。
  2. 劝后台的同事把请求返回的数据全部设置为 String 类型。
  3. 如果涉及到精确计算的问题,请用 NSDecimalNumber 对象了参考

参考
iOS浮点数的转化遇到的坑
iOS开发可能遇到的坑——浮点数的转化显示问题

上一篇下一篇

猜你喜欢

热点阅读