数值类型

Ruby中所有数值都是Numeric类的子类对象,数值都是不可变对象

数值类型的继承关系如下:

Integer是整数,Float是浮点数类型,Rational是分数。

对于整数,要么是Fixnum,要么是Bignum:Fixnum是比较小整数的类型(31个二进制位),Bignum是较大整数的类型。实际上,Ruby中的整数可以变得任意大。但是浮点数不会任意大,浮点数位数达到一点程度后会溢出到正、负无穷

Fixnum和Bignum之间在需要的时候会自动转换:当一个初始为Bignum类型的变量值变小后,会自动转换成Fixnum类型;同理,Fixnum的变量也会在它变得足够大时转换成Bignum类型。

对于分数,只需要在某个数后面加上一个后缀字母r,就会自动转换为分数形式。例如0.3r等价于分数(3/10)2r等价于2/1r等价于分数形式(2/1)。在Kernel模块中有一个Rational方法,可以用来将各种类型转换成分数形式。

关于算术操作的类型转换

当算术运算的两个操作数中,有一个是Float类型,那么整数类型将转换成Float类型进行运算,运算结果也都是Float类型

  1. >> 2 * 2.5
  2. => 5.0
  3. >> 1.0 + 2
  4. => 3.0
  5. >> 5.0/2.5
  6. => 2.0
  7. >> 5.0/2
  8. => 2.5

对于整数除法,即两个数都是整数的除法,那么除法得到的结果将是截断后的整数。对于结果为负数的整数除法,将取比它精确结果更小的整数。也就是说,Ruby中的整数除法采取的是地板除法(floor)所以,(-a)/b等价于a/(-b),但是可能不等价于-(a/b)

  1. >> 5/2
  2. => 2
  3. >> -3/2 # (-a)/b
  4. => -2
  5. >> 3/-2 # a/(-b)
  6. => -2
  7. >> -(3/2) # -(a/b)
  8. => -1

浮点数是不精确的,所以不要在浮点数参与运算的时候对浮点数做等值比较。非要比较,可以通过减法运算,跟一个足够小的值做大小比较,但也别小过头了。例如,(0.4-0.1)和0.3做等值比较:

  1. >> (0.4 - 0.1) == 0.3
  2. => false
  3. >> 0.4 - 0.1
  4. => 0.30000000000000004
  5. >> ( 0.4 - 0.1 ) - 0.3 < 0.00001 # 这是正确的浮点数参与运算的等值比较方式
  6. => true
  7. >> ( 0.4 - 0.1 ) - 0.3 < 0.0000000000000000000001
  8. => false

可以使用Rational分数来比较:

  1. >> (0.4r-0.1r) == 0.3r #=> true
  2. >> 0.4r #=> (2/5)
  3. >> 0.1r #=> (1/10)
  4. >> 0.4r-0.1r #=> (3/10)
  5. >> 0.3r #=> (3/10)

也可以使用BigDecimal类来进行运算,它采用的是十进制表示法来表示浮点数,而Float采用的是二进制表示法表示。只不过BigDecimal的运算速度要比正常的浮点数速度慢上很多个数量级,当然,对于普通的财务运算等领域也足够了,只是在进行科学运算的时候,BigDecimal就不够了。另外,BigDecimal不是内置类,只是一个标准库,需要先导入。

  1. require "bigdecimal"
  2. (BigDecimal("0.4") - BigDecimal("0.1")) == BigDecimal("0.3") #=> true

以下是几种浮点数运算等值比较的效率高低(比较100W次):

  1. # 直接使用浮点数比较,比较是不精确的
  2. $ time ruby -e '1000000.times {|x| (0.4-0.1) == 0.3 }'
  3. real 0m0.147s
  4. user 0m0.063s
  5. sys 0m0.078s
  6. # 直接使用浮点数做不等值比较,比较是精确的
  7. # (多次测试,速度比上面要慢一点点,多了次运算)
  8. $ time ruby -e '1000000.times {|x| (0.4-0.1) - 0.3 < 0.00001 }'
  9. real 0m0.158s
  10. user 0m0.094s
  11. sys 0m0.063s
  12. # 使用分数字面量,比较是精确的
  13. $ time ruby -e '1000000.times {|x| (0.4r-0.1r) == 0.3r }'
  14. real 0m0.248s
  15. user 0m0.188s
  16. sys 0m0.094s
  17. # 使用Kernel中的Rational()
  18. $ time ruby -e '1000000.times {|x| (Rational("0.4") - Rational("0.1")) == Rational("0.3") }'
  19. real 0m0.630s
  20. user 0m0.563s
  21. sys 0m0.063s
  22. # 使用bigdecimal
  23. $ time ruby -r"bigdecimal" -e '1000000.times do |x|
  24. (BigDecimal("0.4") - BigDecimal("0.1")) == BigDecimal("0.3")
  25. end'
  26. real 0m1.079s
  27. user 0m0.953s
  28. sys 0m0.125s

可见,使用分数字面量或浮点数不等值比较的效率是比较可取的,而使用Kernel.Rational()或BigDecimal()的效率相比之下都比较差。

对于Ruby中的取模%运算,也是支持浮点数的。

  1. >> 1.5 % 0.4
  2. => 0.29999999999999993

指数运算时,采取的是Fortran里的优先级模式,和Perl是一样的:从右向左计算。例如3 ** 4 ** 2等价于3 ** (4 ** 2),即其值为3 ** 16

  1. >> 3 ** 4 ** 2
  2. => 43046721
  3. >> 3 ** 16
  4. => 43046721

指数运算的指数支持浮点数、负数,只是指数涉及到整数除法运算时需要注意,因为对于整数除法,Ruby默认采用的是floor除法:

  1. x ** 4
  2. x ** -1 # 即x分之1
  3. x ** (1/3.0) # 即x的立方根
  4. x ** (1/4) # 1/4=0,等价于x ** 0,即结果为1
  5. x**(1.0/4.0) # 即x的四次方根

虽然,数值是不可变对象,但是对于整数来说,它支持索引查找各个二进制位上的值,只是不允许修改。

  1. >> printf "%b\n", 12345
  2. 11000000111001 # 这是十进制12345对应的二进制数
  3. >> x[0]
  4. => 1
  5. >> x[1]
  6. => 0
  7. >> x[4]
  8. => 1
  9. >> x[5]
  10. => 1
  11. >> x[6]
  12. => 0
  13. >> x[11]
  14. => 0
  15. >> x[12]
  16. => 1

所以,要判断一个数是否为偶数,就非常容易了:

  1. x[0] == 0 # 偶数返回true,奇数返回false

Ruby中的数值的更多相关文章

  1. ruby中symbol

    Symbol 是什么 Ruby 是一个强大的面向对象脚本语言(本文所用 Ruby 版本为1.8.6),在 Ruby 中 Symbol 表示“名字”,比如字符串的名字,标识符的名字. 创建一个 Symb ...

  2. Ruby中的常量:引号、%符号和heredoc

    数值字面量 没什么好说的,唯一需要说明的是分数字面量:数值后加上一个后缀字母r表示分数字面量. # 整数字面量 0 1 100 10_000_001 # 千分位 # 浮点数字面量 0.1 1.0 1. ...

  3. 谈谈Ruby中的类变量

    Ruby中的类变量,很多文章都是不太建议使用的,主要原因在于他的一些特性容易导致犯一些错误,尤其在广泛使用元编程的时候. 初步接触类变量可能觉得他跟C++的类静态成员和Java中的静态变量没什么区别, ...

  4. [翻译]理解Ruby中的blocks,Procs和lambda

    原文出处:Understanding Ruby Blocks, Procs and Lambdas blocks,Procs和lambda(在编程领域被称为闭包)是Ruby中很强大的特性,也是最容易引 ...

  5. 理解Ruby中的作用域

    作用域对于Ruby以及其它编程语言都是一个需要理解的至关重要的基础知识.在我刚开始学习ruby的时候遇到很多诸如变量未定义.变量没有正确赋值之类的问题,归根结底是因为自己对于ruby作用域的了解不够, ...

  6. [No000010]Ruby 中一些百分号(%)的用法小结

    #Ruby 中一些百分号(%)的用法小结 #这篇文章主要介绍了Ruby 中一些百分号(%)的用法小结,需要的朋友可以参考下 what_frank_said = "Hello!"#% ...

  7. Ruby中 使用Builder Xml Markup 操作XML

    =begin Ruby中 使用Xml Markup 轻松的对XML文档操作, 项目地址:http://builder.rubyforge.org/ 使用之前我们需要安装Builder xml mark ...

  8. Ruby中Block, Proc, 和Lambda

    Block Blocks就是存放一些可以被执行的代码的块,通常用do...end 或者 {}表示 例如: [1, 2, 3].each do |num| puts num end [1, 2, 3]. ...

  9. [Ruby学习总结]Ruby中的类

    1.类名的定义以大写字母开头,单词首字母大写,不用"_"分隔 2.实例化对象的时候调用new方法,实际上调用的是类里边的initialize方法,是ruby类的初始化方法,功能等同 ...

随机推荐

  1. OpenGL(二十四) VAO、VBO和着色器使用示例

    1. 新建一个工程,新建一个头文件Shader.h,内容如下: #ifndef _SHADER_H_ #define _SHADER_H_ #include <vector> #inclu ...

  2. 转:PyQt4学习资料汇总 from coderzh

    一个月前研究了下PyQt4,感觉比较不错.相比wxpython,界面美观了很多,并且将界面设计与代码逻辑很好的分离了开来.关于PyQt4的资料也不少,这里我将我找到的资料汇总一下,以防自己以后忘得一干 ...

  3. C# PrintDocument 打印表格

    1.封装好的辅助类: using System; using System.Data; using System.Drawing; using System.Drawing.Printing; usi ...

  4. 大数据_zookeeper环境搭建中的几个坑

    文章目录 [] Zookeeper简介 关于zk的介绍, zk的paxos算法, 网上已经有各位大神在写了, 本文主要写我在搭建过程中的几个极有可能遇到的坑. Zookeeper部署中的坑 坑之一 E ...

  5. [Android] 环境优化配置Android Studio发展NDK

    ======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 站点:www. ...

  6. C#基础:ref和out的区别 [转]

    ref和out的区别在C# 中,既可以通过值也可以通过引用传递参数.通过引用传递参数允许函数成员更改参数的值,并保持该更改.若要通过引用传递参数, 可使用ref或out关键字.ref和out这两个关键 ...

  7. XAML的命名空间

    原文:XAML的命名空间 一个最简单的XAML例子   <Window x:Class="WpfApplication1.MainWindow" xmlns="ht ...

  8. liunx 桥接 上网 ip配置 外部网络访问

    一.设置VMware 在vmware的[编辑]-->[虚拟网络编辑器]设置:将VMnet0设置为“桥接”,并桥接到宿主机器的网卡(可以是有线或者无线网络).   二.设置虚拟机系统(以cento ...

  9. How do you create a DynamicResourceBinding that supports Converters, StringFormat?

    原文 How do you create a DynamicResourceBinding that supports Converters, StringFormat? 2 down vote ac ...

  10. 图像滤镜艺术--编码基础(Photoshop基础变换的代码实现)

    原文:图像滤镜艺术--编码基础(Photoshop基础变换的代码实现) 自从上一篇博客写完之后,到现在已经有段时间了,这段时间不是不想接着写,只是想做的更好了在写出来给大家看呵呵. 今天,我将给大家介 ...