博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Objective-C中浮点数表示时精度的小坑
阅读量:6706 次
发布时间:2019-06-25

本文共 3022 字,大约阅读时间需要 10 分钟。

本文迁移自本人简书账号, 后续不会再在简书更新文章, 具体原因可以查看

发现问题

近日测试的童鞋告诉我, 你家APP的四舍五入有毛病. 明明是1.895 => 1.90, 为何出来的结果是1.89. 打死不信, 明明用的是四舍五入, 为何Format出来结果竟是如此. 于是花了小半天的时间, 才发现问题症结所在 -- [NSString stringWithFormat:]

原因

You should only ever do this while formatting a number for display to the end user, because there is no guarantee that.

类同于printf不保证实现四舍五入, [NSString stringWithFormat:]方法也不能保证实现四舍五入, 作为数字描述信息的展示, 永远只能是近似, 更何况浮点型数据在计算机存储的精度是不准确且有限的.

/********************************************************************************    Base floating point types         Float32         32 bit IEEE float:  1 sign bit, 8 exponent bits, 23 fraction bits        Float64         64 bit IEEE float:  1 sign bit, 11 exponent bits, 52 fraction bits          Float80         80 bit MacOS float: 1 sign bit, 15 exponent bits, 1 integer bit, 63 fraction bits        Float96         96 bit 68881 float: 1 sign bit, 15 exponent bits, 16 pad bits, 1 integer bit, 63 fraction bits            Note: These are fixed size floating point types, useful when writing a floating          point value to disk.  If your compiler does not support a particular size           float, a struct is used instead.          Use of of the NCEG types (e.g. double_t) or an ANSI C type (e.g. double) if          you want a floating point representation that is natural for any given          compiler, but might be a different size on different compilers.*********************************************************************************/复制代码

Cocoa框架针对浮点基本类型也有详细的描述, 超过7位(包括小数点整数部分)的Float32数精度本身已不可靠, 如果再依赖此数据进行format, 结果可想而知.

解决思路

既然浮点型数据的存储和计算自有其规则, 自然应该按照规则来办事, 才能得出正确的结果. 作为成熟的Cocoa框架, 必然有针对性的API做浮点型数据的Format处理. 以下是改造的内容:

@implementation ODMNumberFormatter+ (ODMNumberFormatter *)shareInstance {    static ODMNumberFormatter *instance;    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        instance = [[ODMNumberFormatter alloc] init];        instance.numberFormatter = [[NSNumberFormatter alloc] init];        instance.numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;        instance.numberFormatter.roundingMode = kCFNumberFormatterRoundHalfUp;    });    return instance;}+ (NSString *)roundDecimalWithFormat:(NSString *)format value:(double)value {    NSNumberFormatter *numberFormatter = [self shareInstance].numberFormatter;    numberFormatter.positiveFormat = format;    return  [numberFormatter stringFromNumber:[NSNumber numberWithDouble:value]];}@end复制代码

结果

测试用例如下:

NSLog(@"距离为:%@", [ODMNumberFormatter roundDecimalWithFormat:@"0.##" value:1.995]);NSLog(@"距离为:%@", [ODMNumberFormatter roundDecimalWithFormat:@"0.00" value:1.894]);NSLog(@"距离为:%@", [ODMNumberFormatter roundDecimalWithFormat:@"0.00" value:1.895]);NSLog(@"距离为:%@", [ODMNumberFormatter roundDecimalWithFormat:@"0.00" value:1.899]);NSLog(@"距离为:%@", [ODMNumberFormatter roundDecimalWithFormat:@"0.00" value:1.900]);复制代码

测试结果如下:

距离为:2距离为:1.89距离为:1.90距离为:1.90距离为:1.90复制代码

结论

数据处理在不要求精度的APP中可以不用做什么理会, 但是如果考虑到数据不同精度的表达和计算时, 一定要充分考虑各种因素, 谨慎处理. 以免犯下

鸣谢

感谢本司的测试童鞋和的支持, 发现并及时填上了这个坑.

转载地址:http://gyblo.baihongyu.com/

你可能感兴趣的文章
手把手教你在多种无监督聚类算法实现Python(附代码)
查看>>
第4章 Keras入门
查看>>
手工修复ie浏览器
查看>>
BATJ互掐,哪家AI公司首先达到万亿美元市值? | 新智元AI技术峰会论坛
查看>>
hdu 1232 畅通工程 (并查集)
查看>>
MySql的用户权限
查看>>
java中finally和return的执行顺序
查看>>
Hibernate5-一对多双向关联-左外连接-HQL
查看>>
H3C防火墙出厂空配置管理口无法WEB登录
查看>>
使用NetWeaver创建数据库连接
查看>>
Spring事物、面向切面编程、依赖注入简介
查看>>
Java 中带参带返回值方法的使用
查看>>
开发中的各种时间格式转换(一)
查看>>
iSCSI安全之密码认证
查看>>
MySQL运维命令大全
查看>>
MySQL分区表(优化)
查看>>
linux定时任务crond那些事!
查看>>
mysql慢日志分析工具之mysqlsla学习笔记
查看>>
nginx基本配置与参数说明
查看>>
修改防火墙
查看>>