c++ - 将十进制数转换为有理数时的精度问题

标签 c++ c double rational-number

我在将 double (例如 N)转换为 p/q 形式(有理数形式)时遇到问题,为此我有以下策略:

  1. 将双 N 乘以一个大数,比如 $k = 10^{10}$
  2. 然后 p = y*kq = k
  3. gcd(p,q)并找到 p = p/gcd(p,q)q = p/gcd(p,q)

N = 8.2 ,如果我们用笔和纸来解决,答案是正确的,但是作为8.2表示为 8.19999999N (double),它会导致有理数形式转换出现问题。

我尝试了其他方式:(我使用了一个大号 10^k 而不是 100)

if(abs(y*100 - round(y*100)) < 0.000001) y = round(y*100)/100

但是这种方法也不能始终给出正确的表示。

有什么方法可以进行从 double 到 p/q 的等效转换?

最佳答案

浮点运算非常困难。正如评论中所提到的,部分困难在于您需要用二进制表示您的数字。

例如,数字 0.125 可以用二进制表示:

0.125 = 2^-3 = 0b0.001

但数字 0.12 不能。

至11位有效数字:

0.12 = 0b0.00011110101

如果将其转换回十进制,则错误变得很明显:

0b0.00011110101 = 0.11962890625

所以如果你写:

double a = 0.2;

机器实际做的是找到它可以在 double 据类型中保存的最接近 0.2 的二进制表示。这是一个近似值,因为正如我们在上面看到的那样,0.2 不能用二进制精确表示。

一种可能的方法是定义一个“epsilon”,它确定您的数字与最接近的可表示二进制 float 的接近程度。

这是一篇关于 float 的好文章:

https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

关于c++ - 将十进制数转换为有理数时的精度问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48730844/

相关文章:

c++ - 如何绕轴旋转点云?

c++ - 乒乓 Racket 未按预期运行

c - BLAKE2 输入参数

objective-c - C 和 Objective-C 中指针的区别

c++ - C/C++ 以一定的精度高效地四舍五入小数

c++ - 调整字节数组的大小

c++ - waitpid() 后来自 WTERMSIG 宏的异常信号编号

Python C API 在不构建元组的情况下返回多个值/对象

C++ 函数返回 'inf' 而不是 double

java - 将对象(double 类型)转换为 int