在《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)。但我不知道这为什么不精确,你为什么期望这个结果。我不认为有任何四舍五入,所以这就是为什么没有提到。

编辑
舍入是转换成十进制时产生的副作用。因为在二进制表示中`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
> 将double转换为BigDecimal,使用Double.toString(double)方法提供的double的正常字符串表示。
Double.toString
> m或a的小数部分必须打印多少位数字?必须至少有一位数字来表示小数部分,在此之后,需要多少位数字就能唯一区分出该值,但不多于此。也就是说,假设x是此方法生成的十进制表示所表示的精确数学值,那么d必须是离x最近的double值;如果两个double值离x一样近,那么d必须是其中之一,且d的尾数的最小有效位必须是0。

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