想法如何写得更好(欧姆法)

时间:2014-06-22 11:57:34

标签: delphi

所以我有一块代码,我觉得可以写得更好。基本上它是一个简单的欧姆定律计算器,它根据输入变量2的用户输出4变量。我只是想知道如何减少给定变量的重复计算。我知道它应该能够完成,但我无法想到如何去做。

这里是onclick事件的代码,你会注意到根据用户的输入,一些unknowen和knowen变量将被重新计算多达4-5次,如果那么 else <我可以填充代码块/ strong>陈述,但我想尝试并提出建议并找到简单的解决方案/想法。

注意:我不是一名专业程序员,只是心理障碍的一个爱好如何减少重新计算。基本上寻找想法如何检测可能的4中的哪个变量已被输入

procedure TForm1.btnCalcClick(Sender: TObject);
var
  fVolt, fAmp, fResist, fWatt, fBattLife, fBattMah: Single;
begin

  // ============ Set all variables to 0 =====================
  fVolt := 0;
  fAmp := 0;
  fResist := 0;
  fWatt := 0;
  fBattLife := 0;
  fBattMah := 0;

  // ========= Input initial variables =======================
  if lblVolts.Text <> '' then
    fVolt := StrToFloat(lblVolts.Text);

  if lblAmps.Text <> '' then
    fAmp := StrToFloat(lblAmps.Text);

  if lblResistance.Text <> '' then
    fResist := StrToFloat(lblResistance.Text);

  if lblWatts.Text <> '' then
    fWatt := StrToFloat(lblWatts.Text);

  if lblBattMah.Text <> '' then
    fBattMah := StrToFloat(lblBattMah.Text);

  // ================== Ohms Law =============================
  if ((fVolt > 0) and (fResist > 0)) then
  begin
    fAmp := fVolt / fResist;
    fWatt := fVolt * fAmp;
  end;

  if ((fVolt > 0) and (fWatt > 0)) then
  begin
    fAmp := fWatt / fVolt;
    fResist := fVolt / fAmp;
  end;

  if ((fVolt > 0) and (fAmp > 0)) then
  begin
    fWatt := fVolt * fAmp;
    fResist := fVolt / fAmp;
  end;

  if ((fAmp > 0) and (fResist > 0)) then
  begin
    fVolt := fResist * fAmp;
    fWatt := fVolt * fAmp;
  end;

  if ((fAmp > 0) and (fWatt > 0)) then
  begin
    fVolt := fWatt / fAmp;
    fResist := fVolt / fAmp;
  end;

  if ((fResist > 0) and (fWatt > 0)) then
  begin
    fVolt := Sqrt(fWatt * fResist);
    fAmp := fWatt / fVolt;
  end;

  // ================= Calculat Battery Life ===================
  if ((fBattMah > 0) and (fAmp > 0)) then
  begin
    fBattLife := ((fBattMah / 1000) / Power(fAmp, 1.25));
    lblBattLife.Text := FormatFloat('0.00 Hrs', fBattLife);
  end;

  // ================ Display Results ==========================
  if ((fVolt > 0) and (fAmp > 0) and (fResist > 0) and (fWatt > 0)) then
  begin
    lblVolts.Text := FormatFloat('0.0', fVolt);
    lblAmps.Text := FormatFloat('0.00', fAmp);
    lblResistance.Text := FormatFloat('0.0', fResist);
    lblWatts.Text := FormatFloat('0.00', fWatt);
  end;

end;

2 个答案:

答案 0 :(得分:0)

我提供了三种方法可以解决这个问题,但我会把编码留给你。

首先,我同意David Heffernan上面所说的话。

创建一个包含6个元素的记录(或类);从表单中读取值到记录中(假设,例如,-1表示缺少值);调用计算缺失值的(单个)方法;使用所有值更新表单。

就内部结构而言,我经常发现在电子表格如何工作方面考虑这样的问题会很有帮助。尝试在Excel中解决它,然后在您的代码中重现它。

第二种方法是将一些逻辑移入GUI并将几种特定方法添加到记录/类中。当您单击“计算”按钮时,它会查看您提供的两个值,然后调用一个方法来获取这两个特定变量并计算其余变量。这会产生一些荒谬的公共方法和一些更私有的方法,尽管方法中的计算都非常简单。

或者,您可以使GUI逻辑更加通用,并根据输入的两个变量首先求解欧姆定律(E = IR)或幂方程(P = IE)。然后解决剩下的问题。你可能需要三种公共方法,以及一些私有方法。对于您的特定问题,我认为这可能是最佳方法。

FWIW,我前段时间写了一个Delphi应用程序,它有几十个像这样的交互变量(在多个级别上),我发现像内部电子表格一样构建它比我试过的其他方法更容易维护。是的,您最终可能会进行一些冗余计算。但问题不在于这种情况下的速度;如果您没有一些很好的方法来组织程序中的计算,那么您将会失去理智,试图修复错误或稍后扩展代码。

无论你如何解决它,你必须有一些逻辑来确定你开始的值,然后需要调用哪些方程以及按什么顺序。您可以将一些分析逻辑移动到GUI中,这反映在记录/类的特定方法或一般方法的最终方式 - 一个全能方法,一些通用方法或一堆特定方法。最后,您将为同一组输入变量执行相同的计算集。你无法解决这个问题。可变性将取决于您如何调用这些计算。

答案 1 :(得分:0)

如果你的问题确实是'如何进行速度优化?'当你在寻找速度优化时if / then / else没有任何问题。下面的代码保证计算只进行一次!这是IS速度优化。

procedure TForm1.btnCalcClick(Sender: TObject);
var
  fVolt, fAmp, fResist, fWatt, fBattLife, fBattMah: Single;
begin
  // ========= Input initial variables =======================
  fVolt := StrToFloatDef(lblVolts.Text, 0);
  fAmp := StrToFloatDef(lblAmps.Text, 0);
  fResist := StrToFloatDef(lblResistance.Text, 0);
  fWatt := StrToFloatDef(lblWatts.Text, 0);
  fBattMah := StrToFloatDef(lblBattMah.Text, 0);

  // ================== Ohms Law =============================
  if (fVolt > 0) then
   if (fResist > 0)) then
    begin
     fAmp := fVolt / fResist;
     fWatt := fVolt * fAmp;
    end
   else
    if (fWatt > 0) then
     begin
      fAmp := fWatt / fVolt;
      fResist := fVolt / fAmp;
     end
    else
    if (fAmp > 0) then
     begin
      fWatt := fVolt * fAmp;
      fResist := fVolt / fAmp;
     end
    else
  else

  if (fAmp > 0) then
   if (fResist > 0))
    begin
     fVolt := fResist * fAmp;
     fWatt := fVolt * fAmp;
    end
   else
    if (fWatt > 0) then
     begin
      fVolt := fWatt / fAmp;
      fResist := fVolt / fAmp;
     end
    else
   else

     if ((fResist > 0) and (fWatt > 0)) then
      begin
       fVolt := Sqrt(fWatt * fResist);
       fAmp := fWatt / fVolt;
      end
     else
  else
    begin
     ShowMessage('Error');
     EXIT;
    end;

  // ================= Calculat Battery Life ===================
  if (fBattMah > 0) then
   begin
    fBattLife := ((fBattMah / 1000) / Power(fAmp, 1.25));
    lblBattLife.Text := FormatFloat('0.00 Hrs', fBattLife);
   end;

  // ================ Display Results ==========================
  if ((fVolt > 0) and (fAmp > 0) and (fResist > 0) and (fWatt > 0))  //You should be able to get rid of this.
  then
   begin
    lblVolts.Text := FormatFloat('0.0', fVolt);
    lblAmps.Text  := FormatFloat('0.00', fAmp);
    lblResistance.Text := FormatFloat('0.0', fResist);
    lblWatts.Text := FormatFloat('0.00', fWatt);
   end
  else
    ShowMessage('Error');

end;

我没有尝试编译代码。正如其他人建议的那样,您也可以将算法与GUI分开。使用这样的记录传递参数:

type 
  MyRec= record
    fVolt, 
    fAmp, 
    fResist, 
    fWatt, 
    fBattLife, 
    fBattMah: Single;
  end;