怎样用c语言写一个将小数转化成最简分数的算法

2022-03-26 科技 265阅读
算法很简单,程序中已经说明。重要的是系统对浮点数是有修正的,导致结果出现问题。
如何解决,详见程序。

//#include"stdafx.h"//VS默认使用
#include
#include
#include
#pragmawarning(disable:4996)
//为了最大限度支持(目前)小数,整数定义成:__int64
//支持32位:以下分别为int(__int32)1E8
#defineZHENGSHU__int64
#defineXIAOSHUDIANZUOYI1E15//double最多只能确精确到15位有效数字
#defineXIUZHENG1E-16//用于修正浮点数计算误差
int_tmain(intargc,_TCHAR*argv[])
{
//怎样用c语言写一个将小数转化成最简分数的算法
//开始
doublexs=0.000625;//为了简便,直接指定。也可以让用户输入
//scanf("%lf",&xs);
ZHENGSHUfz,fm,zs,k,fh;
//数学算法是:如0.123456=123456/1000000,然后约分
//实现第一步转换
if(xs<0)
{
fh=-1;
xs=-xs;
}
else
{
fh=1;
}
zs=(ZHENGSHU)xs;//支持假分数
//计算整数部分的有效数位数
k=1;
while(zs/k>0)
k*=10;
xs-=(double)zs;
fm=XIAOSHUDIANZUOYI/k;//分母
xs=(double)((ZHENGSHU)((xs+XIUZHENG*k)*fm))/fm;//修正浮点数计算误差
xs+=XIUZHENG;//修正浮点数计算误差
fz=(ZHENGSHU)(xs*fm);//分子

for(;;)//这样循环,是因为C/C++中,for循环效率最高
{//约去多乘的10的倍数
if((fz%10==0)&&(fm%10==0))
{
fz/=10;
fm/=10;
}
else
{
break;
}
}
//实现第二步:约分。以下看起来有点麻烦,目的是为了减少算法的时间复杂的
while((fz%2==0)&&(fm%2==0))
{//将公约数2约尽
fz/=2;
fm/=2;
}
k=3;
for(;;)
{
while((fz%k==0)&&(fm%k==0))
{
fz/=k;
fm/=k;
}
k+=2;
if(k>(ZHENGSHU)sqrt(fz))
break;
}

//将整数部分加上,形成假分数。如果原数为不为0整数,则化成分母为1的假分数
//如果原数为0,则化成分子为0,分母为1。
if(fz==0)
{
fz=fh*zs;
fm=1;
}
else
{
fz=fh*(fz+fm*zs);
}
//结束

//显示一下结果
printf("%lf=%lld/%lld\n",fh*(zs+xs),fz,fm);
//printf("%lf=%ld/%ld\n",fh*(zs+xs),fz,fm);//32位
system("pause");//防止窗口一闪而退
return0;
}
声明:你问我答网所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流。若您的权利被侵害,请联系fangmu6661024@163.com