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

Discussion in '编程心得' started by fht523, Jun 24, 2009.

  1. fh

    fht523 New Member Member

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

    znxia New Member Member

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

    fht523 New Member Member

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

    znxia New Member Member

    给分吧。思路: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;
     
  5. zn

    znxia New Member Member

    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;
     
  6. fh

    fht523 New Member Member

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

    fht523 New Member Member

    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;