分享你的想法,请填写2024 Clojure现状调查!

欢迎!请查阅关于页面了解有关如何使用此功能的一些更多信息。

+1
文档
重新标记

它说

返回num的有理化值

但(rationalize 1.6)的结果是8/5,而不是预期的3602879701896397/2251799813685248。并未记录执行了何种舍入。

2个回答

0

选定了
0
by

为什么你期望3602879701896397/2251799813685248?

by
因为它代表了字面量`1.6`的数字,并且文档中没有提到四舍五入。我已经检查了Common Lisp
```
(print (rationalize 1.6d0))
(print (rational 1.6d0))
```
```
8/5
3602879701896397/2251799813685248
```
所以`rationalize`和`rational`行为相同,但精确转换的调用函数是`rational`,如果clojure中的唯一转换函数是不精确的且其行为未记录的话,如何在遇到这个问题之前知道这一点?
by
`rationalize`通过寻找比例输入与10的幂之间的GCD,并用这个GCD表示分子和分母,所以这将始终是一个简化的分数(在这里是根据gcd 2将16/10简化),但我不明白这是如何不精确的,或者你为什么期望这个结果。我没有发现任何舍入,这就是为什么没有提到它。
by
编辑 by
四舍五入是将数字转换为十进制时产生的副作用,因为双精度字面量 `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`
BigDecimal.valueOf
> 将一个双精度数转换为 BigDecimal,使用 Double.toString(double) 方法提供的双精度数的规范字符串表示形式。
Double.toString
> 对于 m 或 a,必须打印多少位小数?必须至少有一位小数来表示小数部分,并且在此之后,可以有更多的位,但不能超过更多的位,只要足以唯一区分该值和类型 double 的相邻值。也就是说,假设 x 是此方法产生的十进制表示形式所表示的确切数学值。那么 d 必须是与 x 最接近的双精度值;如果两个双精度值与 x 同样接近,那么 d 必须是其中一个,且 d 的尾数最低位必须是 0。

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