您的位置:首页 > 编程语言

编程之美 - 浮点数的精确表示

2016-04-14 21:44 381 查看
问题描述:
如何将浮点数(小数)转换为分数的形式,这样可以更精确的表达出浮点数的值。

问题分析:
小数可以分为两种,有限小数和无限循环小数。

有限小数的处理相对简单:
只要把它乘以10的N次方,转换为整数,再和10的N次方都除以它们的最大公约数即可。
例如:0.25 把它乘以 10的2次方 变成25, 25/100 分子分母除以最大公约数25变成1/4即可。

无限循环小数的处理要复杂一些:
书中使用了一个有趣的计算方法,它把无限循环小数分为一小数部分和一个循环部分 例如: X=0.a1a2...am(b1b2...bn)
这里a是小数部分,b是循环部分。
1) X先乘以10的m次方,把小数部分变为整数 X*10^m ==> a1a2...am + 0.b1b2...bn(b1b2...bn)
X = (a1a2...am + 0.b1b2...bn(b1b2...bn))/(10^m)

2) 假设 Y = 0.b1b2...bn(b1b2...bn),那么Y可以转换为 Y*10^n = b1b2...bn + 0.b1b2...bn(b1b2...bn)
Y*10^n = b1b2...bn + Y ==> Y = b1b2...bn/(10^n - 1)

3) 把Y的部分代入X的等式中 X = (a1a2...am + b1b2...bn/(10^n - 1))/(10^m)
X = (a1a2...am * (10^n - 1) + b1b2...bn) / ((10^n - 1)*10^m)

例如 0.3(3) = (3*9 + 3) / (9*10) = 30 / 90 = 1/3

实例程序:

程序中的缺陷,如果循环小数位数太多,会造成乘积超过int的范围,造成计算错误。

#include <iostream>

using namespace std;

typedef struct _data
{
unsigned long _a;
unsigned long _b;   // the loop part, if = 0 means no
} data_t;

unsigned long gcb(unsigned long a, unsigned long b)
{
unsigned long temp = 0, r = 0;

// make sure a < b
if (a > b)
{
temp = a;
a = b;
b = temp;
}

r = b % a;
while(r != 0)
{
b = a;
a = r;
r = b%a;
}

return a;
}

void calc(data_t data)
{
unsigned long temp = 0, gcb_val = 0;
unsigned long power_a = 1, power_b = 1;

temp = data._a;
while (temp != 0)
{
temp = temp/10;
power_a *= 10;
}

temp = data._b;
while (temp != 0)
{
temp = temp/10;
power_b *= 10;
}

cout << "a->" << data._a << ":" << power_a << "   b->" <<data._b << ":" << power_b << endl;

// no loop part
if (data._b == 0)
{
gcb_val = gcb(data._a, power_a);
cout << data._a/gcb_val << "/" << power_a/gcb_val << endl;
}
else
{
temp = (data._a * (power_b - 1)) + data._b;
power_b = power_a*(power_b - 1);
gcb_val = gcb(temp, power_b);
cout << temp/gcb_val << "/" << power_b/gcb_val << endl;
}
}

int main()
{
data_t test;
int val = 0;
//test._a = 1; test._b = 0;
//test._a = 23; test._b = 0;
//test._a = 3; test._b = 3;
test._a = 1; test._b = 1;
//test._a = 285714; test._b = 285714;   // error: int is overflow

calc(test);

cin >> val;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: