请在 2024 Clojure 现状调查! 中分享您的观点。

欢迎!有关如何使用本页面的更多信息,请参阅 关于 页面。

+1
文档
重新标记

它说

返回数字的分数值

(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,并用该数值表示分子和分母,所以这总是一个简化分数(所以在本例中,根据gcd 2简化16/10)。但我不明白这怎么是不精确的,你为什么期望这个结果。我相信 wasn't rounding,这就是为什么没有提到。

编辑
四舍五入是将数值转换为十进制的小数点数时的副作用,因为双精度的文字`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。那么 d 必须是最接近 x 的双精度值;或者如果两个双精度值与 x 一样接近,那么 d 必须是其中一个,并且 d 的尾数的最不重要位必须为 0。

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