2024 State of 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的幂之间的最大公约数来工作,并且用这个数表示分子和分母,所以这将始终是简化后的分数(所以在这里基于最大公约数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
> 使用 Double.toString(double) 方法提供的双精度数字的规范字符串表示形式将双精度转换为 BigDecimal。
Double.toString
> m 或 a 的分数部分必须打印多少位数字?分数部分必须至少有一位数字来表示,除此之外,还要有更多的数字,但只需要与双精度值相邻的值唯一区分所需的数字即可。也就是说,假设 x 是此方法产生的十进制表示的精确数学值,它代表了一个有限非零参数 d。那么 d 必须是最接近 x 的双精度值;或者如果有两个双精度值与 x 等距离,那么 d 必须是其中一个,并且 d 的尾数的最不显著位必须是 0。

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