单位转换问题,请教大侠们一下,帮帮小弟(100)

fht523

New Member
Member
#1
现在需要做一个单位转换的东东,转换信息如下:KM M 1000M DM 10DM CM 10MM CM 1000大概的数据库信息就是样子,当然可能人家输入跟这不太一样,/可能是 M KM 0.001这样子,完了需求出任意二个之间的转换
 

znxia

New Member
Member
#2
该信息应该是开发商初始化吧?直接把单位换算到最小的单位上去。即:KM CM 100000M CM 100DM CM 10-----------或者采用递归的方式来计算。
 

fht523

New Member
Member
#3
这里的转换信息可由用户自己定义添加,所以到底是A->B还是B->A都未知,这个肯定是要用递归,但是我就是心里有一个想法,但是还没有写出来,呵呵,谁帮小弟写写,或以前做过差不多的DEMO, 发一个LOOK LOOK,
 

znxia

New Member
Member
#4
给分吧。思路:1>整理用户录入的数据,确保 单位一 比单位二 要大2>根据上面的结果,找出最小单位3>将单位A转化为单位B时,由于不知道A和B谁大谁小,因此,先将2者都转化为最小单位,然后在进行计算。浪费了这么长时间,LZ可不能不给分哦。type _Recove = record NameA: string;
NameB: string;
Count:do
uble;
end;
var Recoves: array of _Recove;
BaseUnit: string;
//最小单位 IsSorted: Boolean;
//是否已经处理过 Count肯定>0了procedure SortData;var I, J: Integer;
S: string;
begin
if IsSorted then
Exit;
for I := Low(Recoves) to High(Recoves)do
begin
if Recoves.Count >= 1 then
Continue;
S := Recoves.NameA;
Recoves.NameA := Recoves.NameB;
Recoves.NameB := S;
Recoves.Count := 1 / Recoves.Count;
end;
for I := Low(Recoves) to High(Recoves)do
begin
BaseUnit := Recoves.NameB;
//最小单位 for J := Low(Recoves) to High(Recoves)do
if AnsiComparetext(Recoves[J].NameA, BaseUnit) = 0 then
begin
BaseUnit := '';
Break;
end;
if BaseUnit <> '' then
Break;
end;
IsSorted := True;
end;
function Convert(SNameA, SNameB: string;
ANumber:do
uble):do
uble;
function _InterConvert(SNameA_, SNameB_: string;
ANumber_:do
uble):do
uble;
var I, J: Integer;
sUnit: string;
begin
if AnsiCompareText(SNameA_, SNameB_) = 0 then
begin
Result := ANumber;
Exit;
end;
for I := Low(Recoves) to High(Recoves)do
if AnsiCompareText(Recoves.NameA, SNameA_) = 0 then
begin
if AnsiCompareText(Recoves.NameB, SNameB_) = 0 then
Result := Recoves.Count * ANumber else
Result := _InterConvert(Recoves.NameB, SNameB_, Recoves.Count * ANumber_);
end;
end;
begin
SortData;
Result := _InterConvert(SNameA, BaseUnit, 1) * ANumber / _InterConvert(SNameB, BaseUnit, 1)end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetLength(Recoves, 4);
Recoves[0].NameA := 'M';
Recoves[0].NameB := 'KM';
Recoves[0].Count := 0.001;
Recoves[1].NameA := 'M';
Recoves[1].NameB := 'DM';
Recoves[1].Count := 10;
Recoves[2].NameA := 'DM';
Recoves[2].NameB := 'CM';
Recoves[2].Count := 10;
Recoves[3].NameA := 'MM';
Recoves[3].NameB := 'CM';
Recoves[3].Count := 1000;
IsSorted := False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Caption := FloatToStr(Convert('CM', 'M', 2));
end;
 

znxia

New Member
Member
#5
Convert函数写错了,更正一下:function Convert(SNameA, SNameB: string;
ANumber:do
uble):do
uble;
function _InterConvert(SNameA_, SNameB_: string;
ANumber_:do
uble):do
uble;
var I, J: Integer;
sUnit: string;
begin
if AnsiCompareText(SNameA_, SNameB_) = 0 then
begin
Result := ANumber_;
Exit;
end;
for I := Low(Recoves) to High(Recoves)do
if AnsiCompareText(Recoves.NameA, SNameA_) = 0 then
begin
if AnsiCompareText(Recoves.NameB, SNameB_) = 0 then
Result := Recoves.Count * ANumber_ else
Result := _InterConvert(Recoves.NameB, SNameB_, Recoves.Count * ANumber_);
end;
end;
begin
SortData;
Result := _InterConvert(SNameA, BaseUnit, 1) * ANumber / _InterConvert(SNameB, BaseUnit, 1)end;
 

fht523

New Member
Member
#6
呵呵,谢谢,我自己写了个方法,我直接从数据库检索的,递归把要继续往下找的二个ID和转到找到的Convert的连乘,以下下次查询的SQL条件当做参数递归传递,一个CONVERT方法就搞掂,不过非常感谢你.100分少了一点,嘿嘿,兄弟穷人,凉解呀.谢谢.
 

fht523

New Member
Member
#7
function AutoConvertUnit(UnitID1,UnitID2:Integer;AConvert:Double =1;AStrCon:string= ''):Double;var vstr1,vstr2,vstr_con:string;
vConvert:Double;
vUnitID:Integer;
begin
result:=0;
vstr1:= 'select * from unitconversion where (unitid_1='+inttostr(UnitID1)+ ' and unitid_2='+ inttostr(UnitID2)+ ') or (unitid_1='+inttostr(UnitID2)+' and unitid_2='+inttostr(UnitID1)+')';
with dm.ExecSqlQuery(vstr1)do
begin
if not IsEmpty then
begin
if FieldByName('unitid_1').AsInteger= UnitID1 then
Result:= fieldbyname('Convert').AsFloat * AConvert;
if FieldByName('unitid_2').AsInteger= UnitID1 then
//这里未做分母不为零的验证,在添加的时候做验证 Result:= (1/fieldbyname('Convert').AsFloat) * AConvert;
Exit;
end;
end;
vstr2:= 'select * from unitconversion where (unitid_1='+inttostr(UnitID1)+ ' or unitid_2='+ inttostr(UnitID1) + AStrCon +')';
with DM.ExecSqlQuery(vstr2)do
begin
First;
while not Eofdo
begin
if FieldByName('unitid_1').AsInteger = UnitID1 then
begin
vConvert:= fieldbyname('Convert').AsFloat;
vUnitID:=FieldByName('unitid_2').AsInteger;
vstr_con:=' and not (UnitID_1='+FieldByName('unitid_1').AsString + ' and unitid_2='+FieldByName('unitid_2').AsString +')';
end else
begin
vConvert:= 1/fieldbyname('Convert').AsFloat;
vUnitID:=FieldByName('unitid_1').AsInteger;
vstr_con:=' and not (UnitID_1='+FieldByName('unitid_2').AsString + ' and unitid_2='+FieldByName('unitid_1').AsString +')';
end;
Result:=AutoConvertUnit(vUnitID,UnitID2,vConvert* AConvert,vstr_con);
if Result <> 0 then
exit;
Next;
end;
end;
end;