要想理解 float 和 double 的取值范围和计算精度,必须先了解小数是如何在计算机中存储的:
举个例子:78.375,是一个正小数。要在计算机中存储这个数,需要把它表示为浮点数的格式,先执行二进制转换:
PS:二进制的小数点和十进制的小数点是不同的。二进制小数点后是2的负幂,十进制是10的负幂。
78.375 的整数部分:
小数部分:
所以,78.375 的二进制形式就是 1001110.011
然后,使用二进制科学记数法,有
注意,转换后用二进制科学记数法表示的这个数,有底有指数有小数部分,这个就叫做浮点数
在计算机中,保存这个数使用的是浮点表示法,分为三大部分:
第一部分用来存储符号位(sign),用来区分正负,这里是 0,表示正数
第二部分用来存储指数(exponent),这里的指数是十进制的 6
第三部分用来存储小数(fraction),这里的小数部分是 001110011
需要注意的是,指数也有正负之分,后面再讲。如下图所示:

比如float类型是32位,是单精度浮点表示法:
符号位(sign)占用1位,用来表示正负数。
指数位(exponent)占用 8 位,用来表示指数。
小数位(fraction)占用 23 位,用来表示小数,不足位数补 0。
而 double 类型是 64 位,是双精度浮点表示法:
符号位占用 1 位,指数位占用 11 位,小数位占用 52 位。
到这里其实已经可以隐隐看出:
指数位决定了大小范围,因为指数位能表示的数越大则能表示的数越大嘛!
而小数位决定了计算精度,因为小数位能表示的数越大,则能计算的精度越大咯!
可能还不够明白,举例子吧:
float 的小数位只有 23 位,即二进制的 23 位,能表示的最大的十进制数为 2 的 23 次方,即 8388608,即十进制的 7 位,严格点,精度只能百分百保证十进制的 6 位运算。
double 的小数位有 52 位,对应十进制最大值为 4 503 599 627 370 496,这个数有 16 位,所以计算精度只能百分百保证十进制的 15 位运算。
PS: 我们常见的科学计算器,比如高中时候用的,一般最大支持的运算位数就是 15 位,超过这个就不够准了。在实际编程中,也是用的 double 类型比较多,因为能够保证 15 位的运算。如果还需要更高精度的运算,则需要使用其他数据类型,比如 java 中的 BigDecimal 类型,能够支持更高精度的运算。
需要注意的是指数可能是负数,也有可能是正数,即指数是有符号整数,而有符号整数的计算是比无符号整数麻烦的。所以为了减少不必要的麻烦,在实际存储指数的时候,需要把指数转换成无符号整数。那么怎么转换呢?
注意到 float 的指数部分是 8 位,则指数的取值范围是 -126 到 +127,为了消除负数带来的实际计算上的影响(比如比较大小,加减法等),可以在实际存储的时候,给指数做一个简单的映射,加上一个偏移量,比如float的指数偏移量为 127,这样就不会有负数出现了。
比如:
指数如果是 6,则实际存储的是 6+127=133,即把 133 转换为二进制之后再存储。
指数如果是 -3,则实际存储的是 -3+127=124,即把 124 转换为二进制之后再存储。
当我们需要计算实际代表的十进制数的时候,再把指数减去偏移量即可。
对应的 double 类型,存储的时候指数偏移量是 1023。
所以用float类型来保存十进制小数78.375的话,需要先转换成浮点数,得到符号位和指数和小数部分。这个例子前面已经分析过,所以:
符号位是0,指数位是6+127=133,二进制表示为10 000 101,小数部分是001110011,不足部分请自动补0。
连起来用 float 表示,加粗部分是指数位,最左边是符号位 0,代表正数:
0 10000101 001110011 00000 00000 0000
如果用 double 来保存。。。自己计算吧,太多 0 了。
作者:Boss呱呱
链接:https://www.zhihu.com/question/46432979/answer/221485161
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行
我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是