热门标签 | HotTags
当前位置:  开发笔记 > 开发工具 > 正文

详解iOS之关于double/float数据计算精度问题

1、我们的app有一个判断,当用户输入的值,小于等于剩余的余额时,给用户弹窗,代码不往下执行 当用户输入 0.01 时,po 一下的结

1、我们的app有一个判断,当用户输入的值,小于等于剩余的余额时,给用户弹窗,代码不往下执行

当用户输入 0.01 时,po 一下的结果是:0.10000.... ,当用户的余额是0.01时,po一下网络请求的返回结果是:0.009999...

当用户输入 66.05时,po  一下的结果是:66.049999...,当用户的余额是66.05时,po一下网络请求的返回结果是:66.049999...

所以,当数据较大时,不会有影响,因为用户输入的数据和网络返回数据都被变成了不精确的小值了;但是,当数据较小时,用户输入的数据没有被转,网络返回的数据被转成了不精确的小值,导致用户输入永远大于网络返回的数据,代码无法往下执行;

解决:使用 NSDecimalNumber 将float、double数据转化成NSDecimalNumber 类型的对象进行 +、-、*、/计算,再取值。

- (double)DecimalNumber:(double)num1 num2:(double)num2 { 
   
  NSDecimalNumber *n1 = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",num1]]; 
   
  NSDecimalNumber *n2 = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",num2]]; 
   
  NSDecimalNumber *n3 = [n1 decimalNumberBySubtracting:n2]; 
   
  return n3.doubleValue; 
} 
// 调用: 
double result = [self DecimalNumber: 2.01 num2: 2]; // 结果为 0.01 

其中:
decimalNumberBySubtracting: n1 - n2,返回 n1 - n2 的结果值
decimalNumberByMultiplyingBy:n1 * n2,
decimalNumberByDividingBy:n1 / n2,
decimalNumberByAdding:n1 + n2,
compare:比较 n1 和 n2,返回比较结果;

2、进行数据的四舍五入获得结果 

- (NSString*)Rounding:(float)number afterPoint:(NSInteger)position 
{ 
  NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode: NSRoundPlain scale: position raiseOnExactness: NO raiseOnOverflow: NO raiseOnUnderflow:NO raiseOnDivideByZero: NO]; 
   
  NSDecimalNumber *floatDecimal = [[NSDecimalNumber alloc] initWithFloat: number]; 
   
  NSDecimalNumber *resultNumber = [floatDecimal decimalNumberByRoundingAccordingToBehavior:handler]; 
   
  return [NSString stringWithFormat:@"%@",resultNumber]; 
} 
// 调用: 
NSString *result = [self Rounding:8.00092 afterPoint:3]; // 结果为 8.001 

其中,参数number是需要四舍五入的数据,position是小数点后保留的位数;

高精度要求

使用系统提供的NSDecimalNumber API进行计算,最后转换为字符串输出显示。NSDecimalNumber转换方法:

#import "NSDecimalNumber+Y_Add.h"

@implementation NSDecimalNumber (Y_Add)

+ (NSDecimalNumber *)y_decimalNumberWithFloat:(float)value{
  
  return [self y_decimalNumberWithFloat:value scale:2];
}

+ (NSDecimalNumber *)y_decimalNumberWithFloat:(float)value scale:(short)scale{
  
  return [self y_decimalNumberWithFloat:value roundingMode:NSRoundBankers scale:scale];
}

+ (NSDecimalNumber *)y_decimalNumberWithFloat:(float)value roundingMode:(NSRoundingMode)roundingMode scale:(short)scale{
  
  return [[[NSDecimalNumber alloc] initWithFloat:value] y_decimalNumberHandlerWithRoundingMode:roundingMode scale:scale];
}

+ (NSDecimalNumber *)y_decimalNumberWithDouble:(double)value{
  
  return [self y_decimalNumberWithDouble:value scale:2];
}

+ (NSDecimalNumber *)y_decimalNumberWithDouble:(double)value scale:(short)scale{
  
  return [self y_decimalNumberWithDouble:value roundingMode:NSRoundBankers scale:scale];
}

+ (NSDecimalNumber *)y_decimalNumberWithDouble:(double)value roundingMode:(NSRoundingMode)roundingMode scale:(short)scale{
  
  return [[[NSDecimalNumber alloc] initWithFloat:value] y_decimalNumberHandlerWithRoundingMode:roundingMode scale:scale];
}
 
/**
 * <#Description#>
 *
 * @return <#return value description#>
 */
- (NSDecimalNumber *)y_decimalNumberHandler{
  
  return [self y_decimalNumberHandlerWithRoundingMode:NSRoundBankers scale:2];
}

- (NSDecimalNumber *)y_decimalNumberHandlerWithRoundingMode:(NSRoundingMode)roundingMode scale:(short)scale{
   NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:roundingMode
                                               scale:scale
                                         raiseOnExactness:NO
                                          raiseOnOverflow:YES
                                         raiseOnUnderflow:YES
                                        raiseOnDivideByZero:YES];
  return [self decimalNumberByRoundingAccordingToBehavior:handler];
}
@end

普通精度要求

使用系统提供的数学运算进行计算,最后转换为字符串输出显示。保留小数点后N位的方法:

/**
 * formatterNumber .00 小数点后两位
 *
 * @param number <#number description#>
 *
 * @return <#return value description#>
 */
+ (NSString *)y_formatterNumber:(NSNumber *)number{
  
  return [self y_formatterNumber:number fractionDigits:2];
}

+ (NSString *)y_formatterNumber:(NSNumber *)number fractionDigits:(NSUInteger)fractionDigits{
    
  NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
  [numberFormatter setMaximumFractionDigits:fractionDigits];
  [numberFormatter setMinimumFractionDigits:fractionDigits];
  
  return [numberFormatter stringFromNumber:number];
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • WebBenchmark:强大的Web API性能测试工具
    本文介绍了一款名为WebBenchmark的Web API性能测试工具,该工具不仅支持HTTP和HTTPS服务的测试,还提供了丰富的功能来帮助开发者进行高效的性能评估。 ... [详细]
  • ArcBlock 发布 ABT 节点 1.0.31 版本更新
    2020年11月9日,ArcBlock 区块链基础平台发布了 ABT 节点开发平台的1.0.31版本更新,此次更新带来了多项功能增强与性能优化。 ... [详细]
  • 默认情况下,Git 使用 Nano 编辑器进行提交信息的编辑,但如果您更喜欢使用 Vim,可以通过简单的配置更改来实现这一变化。本文将指导您如何通过修改全局配置文件来设置 Vim 作为默认的 Git 提交编辑器。 ... [详细]
  • 本文探讨了Python类型注解使用率低下的原因,主要归结于历史背景和投资回报率(ROI)的考量。文章不仅分析了类型注解的实际效用,还回顾了Python类型注解的发展历程。 ... [详细]
  • 利用Node.js实现PSD文件的高效切图
    本文介绍了如何通过Node.js及其psd2json模块,快速实现PSD文件的自动化切图过程,以适应项目中频繁的界面更新需求。此方法不仅提高了工作效率,还简化了从设计稿到实际应用的转换流程。 ... [详细]
  • 在Notepad++中配置Markdown语法高亮及实时预览功能
    本文详细介绍了如何在Notepad++中配置Markdown语法高亮和实时预览功能,包括必要的插件安装和设置步骤。 ... [详细]
  • 七大策略降低云上MySQL成本
    在全球经济放缓和通胀压力下,降低云环境中MySQL数据库的运行成本成为企业关注的重点。本文提供了一系列实用技巧,旨在帮助企业有效控制成本,同时保持高效运作。 ... [详细]
  • 本文将详细探讨 Python 编程语言中 sys.argv 的使用方法及其重要性。通过实际案例,我们将了解如何在命令行环境中传递参数给 Python 脚本,并分析这些参数是如何被处理和使用的。 ... [详细]
  • 本文介绍了在使用 `git push origin --delete ` 命令删除远程分支后,本地 `git branch -a` 仍显示已删除分支的问题,并提供了详细的解决方案。 ... [详细]
  • 处理Android EditText中数字输入与parseInt方法
    本文探讨了如何在Android应用中从EditText组件安全地获取并解析用户输入的数字,特别是用于设置端口号的情况。通过示例代码和异常处理策略,展示了有效的方法来避免因非法输入导致的应用崩溃。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • Docker安全策略与管理
    本文探讨了Docker的安全挑战、核心安全特性及其管理策略,旨在帮助读者深入理解Docker安全机制,并提供实用的安全管理建议。 ... [详细]
  • 本文介绍了.hbs文件作为Ember.js项目中的视图层,类似于HTML文件的功能,并详细讲解了如何在Ember.js应用中集成Bootstrap框架及其相关组件的方法。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 2023年,Android开发前景如何?25岁还能转行吗?
    近期,关于Android开发行业的讨论在多个平台上热度不减,许多人担忧其未来发展。本文将探讨当前Android开发市场的现状、薪资水平及职业选择建议。 ... [详细]
author-avatar
才女与尔同销万古愁
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有