2024 Clojure 状态调查! 中分享您的想法。

欢迎!请参考 关于 页面获取更多关于如何使用该页面的信息。

+1
文档
重新标记

它说

返回 num 的有理值

但是 (rationalize 1.6) 的结果是 8/5,而不是预期的 3602879701896397/2251799813685248。没有说明执行了什么样的舍入。

2 个答案

0

选中
0

为什么你期望 3602879701896397/2251799813685248?

因为它代表的是字面量 `1.6` 的数值,并且文档中没有提到四舍五入。我已经检查了Common Lisp了
```
(print (rationalize 1.6d0))
(print (rational 1.6d0))
```
```
8/5
3602879701896397/2251799813685248
```
所以 `rationalize` 和它所做的相同,而精确转换称为 `rational`,但我在遇到这个问题之前如何知道,因为Clojure中唯一的转换函数既不精确也没有文档说明其行为?
`rationalize` 的工作原理是通过找到缩放输入和10的幂之间的最大公约数,并以该数为分子和分母的因数表示,所以这将始终是一个简化的分数(在这里根据gcd 2简约 16/10)。但我不明白这为什么是不精确的或者你为什么期待这个结果。我相信没有发生四舍五入,所以没有提到。

编辑
四舍五入是转换为十进制的小数点运算产生的副作用,因为双精度浮点字面量 `1.6` 在二进制中代表一个有限小数,但在十进制中是无限的[抱歉,不行;目前正在调查]。因此,`rationalize` 找到一个分数,它在四舍五入到双精度后与同一个数字匹配,这在某些情况下可能很有用,但并不明显,我预计它只是与精确转换一起实现,而不是替代它。与其他语言比较
Python
```
from fractions import Fraction
print(Fraction(1.6))
```
`3602879701896397/2251799813685248`
Ruby
`puts 1.6.to_r`
`3602879701896397/2251799813685248`
Racket
```
#lang racket
(println (inexact->exact 1.6))
```
`3602879701896397/2251799813685248`
by
BigDecimal.valueOf
> 将双精度浮点数转换为 BigDecimal,使用双精度浮点数的规范字符串表示形式,由 Double.toString(double) 方法提供。
Double.toString
> m 或 a 的分数部分必须打印多少位数字?分数部分至少必须有一位数字表示,而且超出此数字后,数字必须全,但不能超过所需区分相邻双精度值。也就是说,假设x是与此方法生成的十进制表示相对应的有限非零数字d的精确数学值。那么d必须是x附近的双精度浮点值;或者如果有两个双精度浮点值与x同样接近,那么d必须是其中一个,且d的尾数的最低有效位必须是0。

`rationalize` 的实现使用了 `BigDecimal.valueOf`,它执行四舍五入。精确转换将是 `new BigDecimal(double)` 构造函数。
by
谢谢!我现在明白了。
...