我正在开发一个解方程组的程序。当它给我结果时,它就像:“x1= 1,36842”,我想得到“1,36842”的分数,所以我写了这段代码。
procedure TForm1.Button1Click(Sender: TObject);
var numero,s:string;
a,intpart,fracpart,frazfatta:double;
y,i,mcd,x,nume,denomin,R:integer;
begin
a:=StrToFloat(Edit1.Text); //get the value of a
IntPart := Trunc(a); // here I get the numerator and the denominator
FracPart := a-Trunc(a);
Edit2.Text:=FloatToStr(FracPart);
numero:='1';
for i:= 1 to (length(Edit2.Text)-2) do
begin
numero:=numero+'0';
end; //in this loop it creates a string that has many 0 as the length of the denominator
Edit3.text:=FloatToStr(IntPart);
y:=StrToInt(numero);
x:=StrToInt(Edit3.Text);
while y <> 0 do
begin
R:= x mod y;
x:=y;
y:=R;
end;
mcd:=x; //at the end of this loop I have the greatest common divisor
nume:= StrToInt(Edit3.Text) div mcd;
denomin:= StrToInt(numero) div mcd;
Memo1.Lines.Add('fraction: '+IntToStr(nume)+'/'+IntToStr(denomin));
end;
它不能正确工作,因为它给我的分数是错误的。有人能帮助我吗?
4条答案
按热度按时间thtygnil1#
您的程式码无法运作,因为您使用的是二进制浮点。而且二进制浮点型别无法表示您尝试表示的十进制数。可表示的二进制浮点数的格式为 s2e,其中 s 是有效数,e 是指数。因此,例如,您无法将0.1表示为二进制浮点值。
最明显的解决方案是使用整数运算来执行计算。根本不要调用StrToFloat。不要接触浮点运算。自己解析输入字符串。定位小数点。使用后面的位数来计算小数位数。去掉任何前导或尾随的零。然后使用整数运算来执行其余操作。
例如,假设输入为
'2.79'
。通过处理文本将其转换为分子和分母变量显然,您必须编写字符串解析例程,而不是使用整数字面值,但这就是例程。
最后,通过求出这两个整数的gcd来完成问题。
底线是,要表示和操作十进制数据,你需要一个十进制算法。而这不包括二进制浮点。
wa7juj8i2#
我建议先定义一个函数GreaterCommonDivisor函数(wiki参考)
这将是Java/C类代码,因为我不熟悉 Delphi
让
然后,乘以
那么此时应该有
(float)x/n == inputnum
这意味着你有一个分数,在这一点上可能不会被简化。
这应该是快速和简单的实施,但:
主要缺陷:
acruukt93#
Continued fractions可以用来找到真实的的有理近似值。下面是JavaScript中的一个实现,我相信移植到 Delphi 是很简单的:
例如,1.36842会转换为26/19。
你可以找到一个实时演示和更多关于这个算法on my blog的信息。
6yoyoihd4#
@Joni我试了1/2,结果是“被零除”的错误;我更正循环,添加:
要避免