急求:正实数整除算法(50分)

  • 主题发起人 主题发起人 phynex
  • 开始时间 开始时间
P

phynex

Unregistered / Unconfirmed
GUEST, unregistred user!
如题,如 0.2与0.6之间能够整除,即结果为整数。
由于计算精度的问题,下列函数求24与72的时候不能得出正确结果。在线等。

function IsMultiple(small, big: Double): Boolean;
begin //倍数关系
Result := False;
small := small * 100;
big := big * 1000;
if small = 0 then
begin
Result := True; Exit
end;
Result := trunc(big / small) = big / small;

if Result then
Result := big / small >= 1 {eg:3/4};
end;
 
写错了, 重贴:

如题,如 0.2与0.6之间能够整除,即结果为整数。
由于计算精度的问题,某些时候不能得出正确结果。在线等。

function IsMultiple(small, big: Double): Boolean;
begin //倍数关系
Result := False;
small := small * 100;
big := big * 1000;
if small = 0 then
begin
Result := True; Exit
end;
Result := trunc(big / small) = big / small;

if Result then
Result := big / small >= 1 {eg:3/4};
end;
 
举例如下:

function IsMultiple(small, big: Double): Boolean;
begin //倍数关系
Result := False;
small := small * 100;
big := big * 1000;
if small = 0 then
begin
Result := True; Exit
end;
Result := trunc(big / small) = big / small;

if Result then
Result := big / small >= 1 {eg:3/4};
end;

procedure test;
var
a, b,c: Double;
begin
a := 21.6;
b := 0.3;
c:=24;
ShowMessage(BoolToStr(IsMultiple(c,a/b), True));//此时出错

end;
 
function IsMultiple(small, big: Double): Boolean;
begin
Result := Abs(Frac(big / small)) < 0.0000001;
end;
 
function IsMultiple(small, big: Double): Boolean;
const
VALUE
begin
//變通一下,假設最大小數位數是10位,足夠了吧...
//把small和big同時乘一個足夠大的整數如10000000000,以消除小數影響
//再分別用Trunc()取整,最後取模
result:= Trunc(big*10000000000) mod Trunc(small*10000000000) = 0
end;
 
//来自:djrj, 时间:2006-6-22 21:14:43, ID:3478870

乘以一个大的数会丢失前面的位数的,如果浮点数不是很小的话。
 
你把这一行改一下行不行:
Result := trunc(big / small) = big / small;
=>
Result := inttostr(trunc(big / small)) = floattostr(big / small);
 
jeffrey_s兄的是正确的,两个浮点数不要直接比较是否相等,而是看相差是否小于某个比较小的值。
 
目前操作数不是很大,介于0.0001至1000之间。
to jeffrey_s:书上确实是讲要以差值小于某个较小值来判断相等,但这个值要取多少呢?

我作了如下修改,但是还是无法保证(验证)正确性:
function IsMultiple(small, big: Integer): Boolean;
begin
Result := big mod small = 0
end;

function IsMultiple(small, big: Double): Boolean;
var
vStr: string;
a, b: Integer;
begin //倍数关系
Result := False;
small := small * 1000;
big := big * 1000;
if small = 0 then
begin
Result := True; Exit
end;
Result := trunc(big / small) = big / small;
if Result then
Result := big / small >= 1 {eg:3/4}
else begin
vStr := UpperCase(FloatToStr(big / small));
if Pos('.', vStr) > 0 then Exit;
if Pos('E', vStr) > 0 then Exit;
a := trunc(small);
b := trunc(big);
Result := IsMultiple(a, b);
end;
end;
 
不用这么麻烦的,用jeffrey_s的那个就行,简单好用。
至于选择的那个比较小的值,可以这么选择:
你的数的范围是0.0001-1000,那么可以看做被除数两个值之间的差值不小于0.0001,而除数的最大值不超过1000,那么这个小值可以取为0.0001/1000,或者为了更精确一点,再除个10。
 
to jeffrey_s:我改为以下在值分别是为0.1, 1.2时也不行.
function IsMultiple(small, big: Double): Boolean;
begin
Result := Abs(Frac(big / small)) < 0.00000001
end;
 
前面的确实不完整。改为:
function IsMultiple(small, big: Double): Boolean;
var
DDiv: Double;
begin
DDiv := big / small;
Result := Abs(Round(DDiv) - DDiv) < 0.00000001
end;
 
没有更多的例子来验证,暂时用以下方法.
function IsMultiple(small, big: Double): Boolean;
var
vStr: string;
a, b: Integer;
begin //倍数关系
Result := False;
small := small * 1000;
big := big * 1000;
if small = 0 then
begin
Result := True; Exit
end;
Result := trunc(big / small) = big / small;
if Result then
Result := big / small >= 1 {eg:3/4}
else begin
vStr := UpperCase(FloatToStr(big / small));
if Pos('.', vStr) > 0 then Exit;
if Pos('E', vStr) > 0 then Exit;
Result := True;
end;
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
461
import
I
后退
顶部