Ruby 中的浮点值是立即数吗?

如何解决Ruby 中的浮点值是立即数吗?

根据Ruby FAQfixnum(持有integer),booleannil是立即数。在我的理解中,一个拥有立即数的对象总是完全一样的,不管它被分配了多少个变量。这在 Ruby 中很容易验证:

# Immediate values
i1 = 1
i2 = 1
i1.object_id  # the same as i2's id
i2.object_id  # the same as i1's id

# Not immediate values
s1 = "1"
s2 = "1"
s1.object_id  # NOT the same as s2's id
s2.object_id  # NOT the same as s1's id

float 似乎也是直接值:

f1 = 2.1
f2 = 2.1
f1.object_id  # the same as f2's id
f2.object_id  # the same as f1's id

但是,我找不到任何关于 float 是直接值的引用。 Ruby 中的浮点值是立即数吗? float 在 Ruby 中如何工作?

解决方法

立即数的概念在 Ruby 中不存在

现在,您可能会问“当 Ruby 没有立即值时,为什么 Ruby 常见问题解答会谈论立即值?”这个问题的答案是,不幸的是,Ruby 社区中的很多文档混淆了编程语言的概念,称为“Ruby”和众多 Ruby 语言之一。实现,不幸的是通常也被称为“Ruby”,尽管它的“官方”名称是“YARV”。

例如,如果您检查 ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification,您将发现没有提及直接值,无论是在该名称下,还是在任何其他名称下的类似概念。它们根本不存在。

还要注意有关您链接到的直接值的部分中的以下警告:

此部分或部分内容可能已过时或需要确认。

所以,我们有两个问题:

  1. 本节讨论一个 Ruby 的具体实现,但并没有说清楚,并且
  2. 即使是特定于实现的信息也已过时。

在当前版本的 YARV 中,Fixnum 不再存在。过去,Integer 是一个抽象类,有两个具体的子类:FixnumBignumFixnum 是直接值,Bignum 不是。

但是,根据您运行的是 32 位还是 64 位,完全相同文字可以是 Fixnum,因此是一个立即数,或者是 {{1} }.在 32 位上 Bignum 可以存储 31 位,在 64 位上 Fixnum 可以存储 63 位。请注意,这仅适用于 YARV,例如JRuby 将在 32 位和 64 位平台上存储 64 位(不仅仅是 63 位)

如今,FixnumFixnum 不再存在,而 Bignum 是具体类,而不是抽象类。但是,优化实际上仍在执行:YARV 仍然在 32 位系统上将 31 位 Integer 优化为 fixnum 并且64 位系统上的 63 位 Integer,JRuby 仍然优化 64 位 Integer

JRuby 对 Integer 进行了很长时间的优化。在 JRuby 中,Float 是直接值。然而,在 YARV 中,没有这样的优化。 Float 不是直接值。然而,最近 YARV 引入了 flonum 的概念。 Flonum 是适合 62 位的 FloatFlonum 是直接值。此外,此优化仅在 64 位平台上执行,flonums 在 32 位平台上完全禁用。

另请注意,FAQ 完全忽略了 Symbol,这些 Object#object_id 在许多实现中都是直接值,包括 YARV。

所以,回答您的问题:

Ruby 中的浮点值是立即数吗?

没有。可能是。其中一些,有时。

不,Float 在 Ruby 中不是直接值,如果“Ruby”指的是“Ruby 编程语言”。 Ruby 语言没有立即值的概念。

也许,Float 是 Ruby 中的直接值,也许不是,如果“Ruby”的意思是“所有现有 Ruby 实现的集合”。在某些实现中,在某些情况下,某些 Float 值可能是也可能不是立即值。

某些 Float 有时是直接值,如果“Ruby”是指“YARV”。在 64 位平台上,Float 的子集是直接值,但不是全部。在 32 位平台上,没有一个是立即值。

无关

你只能通过改变一个值来判断它是否是立即数。但是,执行此类优化的所有值都是不可变的,不能有实例变量,也不能有单例方法或单例类。

因此,实际上无法判断某物是否为直接值。这是一个私有的内部优化细节。

这意味着您可以完全忽略这个概念,因为它无法使您的程序以不同的方式运行。

Float 怎么样?

首先:BasicObject#equal? 是可憎的。它不应该存在。忘记你曾经听说过它。

它违反了面向对象的基本原则之一,即模拟另一个对象的对象应该与该对象无法区分。 (同样适用于 frozen String literals。)

但其次,这里有一个反例:

object_id

糟糕。我破坏了您的测试:{{3}} 不是直接对象,但会自动删除重复数据。

,

在 YARV 中,具有直接值的对象与它们的 object_id 密切相关,类似于它们内部的 VALUE。 (见Creating Extension Libraries for Ruby

具有“立即值”的对象在其 VALUE 中完全编码。因此,此类对象在每个 Ruby 进程中都具有相同的 object_id。 (使用相同的 Ruby 二进制文件)

在 Ruby 中,调用 ObjectSpace._id2ref 是一种检索这些对象的方法:(在某些时候,如果您继续循环,这还将枚举来自核心和 stdlib 的非直接对象)

0.upto(31) do |i|
  printf('%08b  ',i)
  begin
    obj = ObjectSpace._id2ref(i)
    printf('%-10s %s',obj.class,obj.inspect)
  rescue RangeError
    print('-')
  end
  puts
end

输出:(在 64 位机器上)

00000000  FalseClass false
00000001  Integer    0
00000010  Float      2.0
00000011  Integer    1
00000100  -
00000101  Integer    2
00000110  Float      -2.0
00000111  Integer    3
00001000  NilClass   nil
00001001  Integer    4
00001010  Float      2.0000000000000004
00001011  Integer    5
00001100  -
00001101  Integer    6
00001110  Float      -2.0000000000000004
00001111  Integer    7
00010000  -
00010001  Integer    8
00010010  Float      2.000000000000001
00010011  Integer    9
00010100  TrueClass  true
00010101  Integer    10
00010110  Float      -2.000000000000001
00010111  Integer    11
00011000  -
00011001  Integer    12
00011010  Float      2.0000000000000013
00011011  Integer    13
00011100  -
00011101  Integer    14
00011110  Float      -2.0000000000000013
00011111  Integer    15

您可以看到 3 种类型的对象:

  1. falsetruenil

    00000000  FalseClass false
    00001000  NilClass   nil
    00010100  TrueClass  true
    
  2. 整数:

    00000001  Integer    0
    00000011  Integer    1
    00000101  Integer    2
    00000111  Integer    3
    
  3. 浮动:

    00000010  Float      2.0
    00000110  Float      -2.0
    00001010  Float      2.0000000000000004
    00001110  Float      -2.0000000000000004
    

在 64 位机器上,object_id 是一个可以容纳 64 位的 unsigned long

整数的 object_id 以二进制 1 结尾,所以还有 63 位表示覆盖范围的整数值:

-4611686018427387904..4611686018427387903

超出该范围的整数将成为非直接对象。

浮点数的 object_id 以二进制 10 结尾,因此还有 62 位用于对浮点值进行编码,它涵盖了所有(双精度)浮点数的 1/4。这些在内部被称为“flonum”。

64 位机器上 Ruby 2.0 中的 YARV introduced flonums

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-