返回顶部
首页 > 资讯 > 移动开发 >iOS浮点类型精度问题的原因与解决办法
  • 270
分享到

iOS浮点类型精度问题的原因与解决办法

2024-04-02 19:04:59 270人浏览 泡泡鱼
摘要

目录前言如何解决浮点型精度问题四舍五入处理更优的解决方案精度丢失的原因浮点类型的存储方式有效位数指数的存储方式:移位存储double类型总结:输出结果丢失精度原因前言 相信不少人(其

前言

相信不少人(其实我觉得应该是每个人)都遇到过一个问题,那就是当服务端返回的JSON数据中出现了小数时,客户端用CGFloat去解析时总是会出现精度丢失的问题,尤其当遇到敏感数据时,这种精度丢失是完全不能被容忍的,本文会从简单的解决方案和原理出发,一起带大家回顾一下这个其实大家以前都学过但是都忘的差不多了的小问题。

如何解决浮点型精度问题

四舍五入处理


//例如服务端返回了这么一个json
{
    "price":1.9
}

// 客户端解析price后并且打印1.9
CGFloat price = model.price
NSLog(@"%f",price)
得到的结果是 1.8999999999999999

这个时候呢,作为一个咸鱼开发者,可以写下如下代码:

NSLog(@"%.2f",price)
输出:1.89
//不够准确,没关系,还有办法
NSLog(@"f%@",round(price*10)/10);
输出1.9

当然了,还有apple专门为精度问题提供的 NSDecimalNumber类型也可以解决这个问题。NSDecimalNumber的用法非常简单。(至于怎么个简单,请自行百度,别问我,我不百度也写不出来)

更优的解决方案

  • 那么问题来了,作为一个懒到一整年都不愿意写文章的咸鱼中的咸鱼,我应该选择哪种方式去解决这个问题呢?

好的,重头戏来了,接下来,我们上代码!

//服务端必须返回字符串类型,如果服务端没有照做: **请带着锤子和煤气罐去找后端开发人员解决**
@property (nonatomic,copy) NSString *price;

是的,我会选择不解决这个问题,把皮球踢出去,这才是一个合格的开发者该做的事情嘛!

精度丢失的原因

解决浮点精度问题是一个方面,但是如此简单的内容不足以我水完一整篇文章,那么接下来,我们来讲讲为什么好好的数字解析出来,他咋就不准确了呢?

可能很多人都能大概讲出来精度丢失是因为浮点数存储方式的问题,毕竟这玩意儿其实专业对口的筒子们在校的时候都学过,但是大家摸摸自己的小脑袋,嘿,是不是和我一样?全忘光了?

而且鉴于总有些基础很牛逼的面试官和刚好复习过这部分内容的装逼面试官就是喜欢挑这些小问题来刁难咱们这些老年摸鱼程序员,下面我们就来复习一下这部分的知识吧。

浮点类型的存储方式

浮点类型在计算机中的存储方式是以科学计数法的方式来存储的:

例如: 科学计数法表示小数
90.9 => 9.09 x 10^1
8.3  => 8.3 x 10^0

我们以8.3为例子,要存储8.3 (8.3 x 10^0), 首先肯定要将8.3转化为2进制,8转为二进制时1000,那么0.3呢?

年迈的程序员哟,你是不是猛然发现居然忘了小数是如何转化为2进制的呀,放下你准备百度的颤抖的双手,你想要的,我这里都有!

以0.9为例子,将0.9乘以2,得到的数字整数部分为二进制的小数第一位,将结果部分的小数部分取出并再乘以2,取整数部分为第2位,不断重复以上操作,直到结果等于0或者出现循环为止。

0.9 *2 = 1.8  第1位 1
0.8 *2 = 1.6  第2位 1
0.6 *2 = 1.2  第3位 1
0.2 *2 = 0.4  第4位 0
0.4 *2 = 0.8  第5位 0
0.8 *2 = 1.6  第6位 1 出现循环了

那么0.9的二进制就是 0.1 1100 1100 1100 1100... 其中1100无限循环

经过上面一番复习我们知道8.3的二进制可表示为 1000.0 1001 1001 1001... (1001无限循环) 用科学计数法表示则为, 1.000 0 1001 1001 1001 x 2^3

整数部分指数部分小数部分
13.000 0 1001 1001 1001

而我们知道float是4(32位)个字节,在存储时他的每个bit是如下分配的

第31位符号位23-30位(指数位)0-22位(小数位)
13.000 0 1001 1001 1001

有效位数

可以看到尾数部分有23位,但是由于是科学技术法之后任何一个数字都可以用  1.aaa x 2^b 这种形式来表示,所以1可以省略,(这个时候就有人要抬杠了,为啥,那遇到0.aaa x 2^b这种咋办呀! 答曰:b可以是负数啊),那么总共23位的数据实际可以表达的位数其实就是24位。

  • 24位可以表达的最大数字是 16777215 ,如果大于这个数就无法精确表示了。

当然大于16777215一不定是完全不能精确表示的,比如16777216,他的二进制表达形式是1后面带1堆0. 因为他是2的整数次幂,那么后面全是0 所以23位能把该数字存储下来,如果在23位0后面还出现了1就不行了,以此类推,16777215 后面还会有数字刚好可以满足这种2的整数次幂的条件,也可以正确表达。

虽然大于16777215的数字也有部分可以精确表达,但是我们谈精度的话肯定就要精确了,那么能精确表达的数字就只有0-16777215之间的了,16777215之间我们数一下,一共是8位,但是由于最高位1开头并不能全部包含,所以说精度应该是7位有效数子。

另外提一下浮点数的表达范围,这个范围肯定是由指数来确定了,具体是多少我就不算了,大家有兴趣的可以去算一算。

指数的存储方式:移位存储

可以看到指数部分一共是给了8个bit位,由于指数有正负,那么假设我们第一位表示符号位,那么我们可以表示的数字范围为 -127 ~ +127

那么能表示的范围被分为两部分:

  • 1 000000 0~ 1 111111 1 => -0 到 -127

  • 0 000000 0~ 0 111111 1 => +0 到 127

很明显,如果这样会出现一个 -0 和一个 +0,为了避免这个问题所以出现了移位存储:即如果最高位不用来表示符号位,8个bit 可以存储的范围是 0-255,我们重新来规划下两个区间:

  • 00000000 - 01111111 => 0-127 减去127则表示-127-0之前的数字
  • 10000000 - 11111111 => 128-256 减去127则表示1-127之前的数字

这样一来规避了+-0的问题, 上文中所说的8.3 转化为小数后的指数位是3,那么3实际存储的时130,也就是 10000010,我们更新一下实际存储的表格

第31位符号位23-30位(指数位)0-22位(小数位)
110000010.000 0 1001 1001 1001

double类型

double类型是8字节64位,其表示的位数和float所不同只有位数差别,其他都一样,双精度表示的位数如下:

第63位符号位52-62位(指数位)0-51位(小数位)

总结:输出结果丢失精度原因

回到最初的1.9这个数字打印为1.8999999999999999,现在我们应该知道为什么了,因为1.9转2进制时是个无限循环,由于存储的原因后面的循环部分被只被截取了23位,还原回来的十进制数字和原先肯定就不一样了。 同理,如果小数点后面是.5这种5的倍数的小数,打印出来的小数一般都会是正常的,因为.5转2进制时并不是无限循环的。

到此这篇关于iOS浮点类型精度问题的原因与解决办法的文章就介绍到这了,更多相关ioS浮点类型精度问题内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: iOS浮点类型精度问题的原因与解决办法

本文链接: https://lsjlt.com/news/164044.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • iOS浮点类型精度问题的原因与解决办法
    目录前言如何解决浮点型精度问题四舍五入处理更优的解决方案精度丢失的原因浮点类型的存储方式有效位数指数的存储方式:移位存储double类型总结:输出结果丢失精度原因前言 相信不少人(其...
    99+
    2024-04-02
  • iOS浮点类型精度问题的原因与解决办法是什么
    这篇文章主要为大家分析了iOS浮点类型精度问题的原因与解决办法是什么的相关知识点,内容详细易懂,操作细节合理,具有一定参考价值。如果感兴趣的话,不妨跟着跟随小编一起来看看,下面跟着小编一起深入学习“iOS浮点类型精度问题的原因与解决办法是什...
    99+
    2023-06-29
  • JS中浮点数精度问题的分析与解决方法
    目录前言问题的发现浮点数运算后的精度问题toFixed奇葩问题为什么会产生浮点数的存储浮点数的运算解决方法解决toFixed解决浮点数运算精度附:JS浮点数精度问题的一些实用建议总结...
    99+
    2024-04-02
  • 解决Pytorch半精度浮点型网络训练的问题
    用Pytorch1.0进行半精度浮点型网络训练需要注意下问题: 1、网络要在GPU上跑,模型和输入样本数据都要cuda().half() 2、模型参数转换为half型,不必索引到每层...
    99+
    2024-04-02
  • js浮点数精度丢失的问题及解决方法
    本篇内容介绍了“js浮点数精度丢失的问题及解决方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!说明在数学计算中,小数会有一定的误差,这是计...
    99+
    2023-06-20
  • Python中的浮点数计算精度问题的原因和解决方案有哪些?
    Python中的浮点数计算精度问题的原因和解决方案有哪些?在进行浮点数计算时,我们经常会遇到精度问题。这是由于计算机采用二进制来表示浮点数,而不是十进制。由于二进制无法准确表示一些十进制小数,导致了浮点数计算的精度问题。一、浮点数计算精度问...
    99+
    2023-10-22
    解决方案 (solution) 浮点数 (float) 精度问题 (precision issue)
  • python浮点数运算精度问题如何解决
    在Python中,浮点数运算可能存在精度问题,可以采取以下方法解决:1. 使用Decimal模块:Decimal模块提供了精确的十进...
    99+
    2023-08-26
    python
  • Golang浮点数精度丢失问题扩展包的解决方法
    小编给大家分享一下Golang浮点数精度丢失问题扩展包的解决方法,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!PS: 今天在做项目进行精度处理的时候出现精度丢失问题,在这里跟大家分享下扩展包解决方案, 注意:这个问题是可能...
    99+
    2023-06-08
  • C语言中浮点数的精度丢失问题解决
    目录一 先来看一段代码运行结果:二 如何解决(1)浮点数的大小比较(2)含浮点数的表达式和0.0的比较总结一 先来看一段代码 #include<stdio.h> int ...
    99+
    2024-04-02
  • double类型精度丢失问题以及解决方法
    double类型精度丢失问题: (1)加法运算。 public static void main(String[] args) {double number1 = 1;double number2 = 20.2;double number3...
    99+
    2023-09-07
    java android
  • Golang处理浮点数遇到的精度问题怎么解决
    这篇文章主要介绍“Golang处理浮点数遇到的精度问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Golang处理浮点数遇到的精度问题怎么解决”文章能帮助大家解决问题。一、浮点数是什么?浮...
    99+
    2023-06-29
  • Python中的浮点数计算精度问题是如何解决的?
    Python中的浮点数计算精度问题是如何解决的?在计算机科学中,浮点数计算精度问题是常见的挑战之一。由于计算机内部使用有限的比特位来表示浮点数,所以对于某些小数的表示和运算时,可能会出现精度损失的情况。Python作为一门强大的编程语言,提...
    99+
    2023-10-22
    解决 浮点数 精度
  • 如何解决C语言中浮点数的精度丢失问题
    小编给大家分享一下如何解决C语言中浮点数的精度丢失问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一 先来看一段代码#include<stdio.h>...
    99+
    2023-06-26
  • 解决PHP浮点数计算精度丢失的方法
    解决PHP浮点数计算精度丢失的方法 在PHP中,由于浮点数的本质是二进制表示,会导致在进行计算时出现精度丢失的问题。这种问题在一些对精度要求较高的场景下就显得尤为重要。为了避免由于浮点...
    99+
    2024-02-27
    解决方法 php浮点数 计算精度
  • Android 关于“NetworkOnMainThreadException”问题的原因分析及解决办法
    网络收集的原因如下,以及解决办法: 我补充总结一下: 解决办法一: 在操作网络类(socket连接)的activity的protected void onCreate(Bu...
    99+
    2022-06-06
    Android
  • springboot中使用FastJson解决long类型在js中失去精度的问题
    目录使用FastJson解决long类型在js中失去精度问题1.pom中需要将默认的jackson排除掉2.利用fastJson替换掉jacksonspringboot long精度...
    99+
    2024-04-02
  • Java序列化JSON丢失精度问题的解决方法(修复Long类型太长)
    目录原因:解决办法一:解决办法(二):总结Java序列化JSON时long型数值,会出现精度丢失的问题。 原因: java中得long能表示的范围比js中number大,也就意味着部...
    99+
    2024-04-02
  • JS超出精度数字问题的解决方法
    精度问题最通俗易懂的解释 比如一个数 1÷3=0.33333333...... 大家都知道3会一直无限循环,数学可以表示,但是计算机要存储,方便下次取出来再使用,但0.333333...
    99+
    2024-04-02
  • 乱码问题的原因及解决方法
    这篇文章主要讲解了“乱码问题的原因及解决方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“乱码问题的原因及解决方法”吧!PHP乱码问题1、PHP 如何处理上传的CSV文件?可以用fgetcs...
    99+
    2023-06-17
  • Android实现类似IOS右滑返回的效果(原因分析及解决办法)
    使用类库SwipeBackLayout https://github.com/Issacw0ng/SwipeBackLayout 出现的问题: 1. 主Activity返回...
    99+
    2022-06-06
    IOS Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作