【问题标题】:How do I define the amount of decimal places in a Single-type variable in Inno Setup?如何在 Inno Setup 中定义 Single-type 变量中的小数位数?
【发布时间】:2012-11-11 08:18:06
【问题描述】:

我需要计算我的设置中所有组件的总大小。由于一些自定义代码,我无法使用 Inno Setup 的内部功能。

问题在于组件共享大量文件。所以我为每个组件定义了一个字符串,其中包含他们使用的文件的变量。然后我将这些字符串添加到单个字符串中,如果在该字符串中找到某个变量,则将文件的大小(以字节为单位)添加到类型为Single 的变量“大小”中。 最后“大小”显示安装需要多少空间。

实际上这很好用,但我想在下一页显示以 GB 为单位的大小。 但是函数FloatToStr在小数点后添加了很多数字,而我只想有两个。

这是脚本(问题出现在最后几行):

function NextButtonClick(CurPageID: Integer): Boolean;
var
  size: Single;

  if (CurPageID = wpSelectDir) then { I have swapped the Components and SelectDir pages }
  begin

  size := 0; { this will contain the size in the end }
  xg := '';  { this is the string which contains the list of files needed by every single component }
  for I := 0 to GetArrayLength(ComponentArray) - 1 do
  if IsComponentSelected(ComponentArray[I].Component) then
  begin
    xg := xg + ComponentArray[I].GCF; 
  end;    
  { here the files are being added to the string, everything's working as intended.. }


  MsgBox(xg, mbInformation, MB_OK); { this is for testing if the string has been created correctly }
  if Pos('gcf1', xg) > 0 then size := size + 1512820736; { here the Pos-function searches for the given string and if it is found it adds the value to "size", ok... }
  if Pos('gcf2', xg) > 0 then size := size + 635711488;
  if Pos('gcf3', xg) > 0 then size := size + 286273536;
size := size / 1024 / 1024 / 1024; { now all sizes have been added and the number is converted to be displayed GB, not bytes }
  { Format('%.2n', [size]); }
  { size := (round(size * 10) / 10); }
  { size := Format('%.2n', [size]); }
  { FloatToStr(size); }
  MsgBox(FloatToStr(size), mbInformation, MB_OK); { Here the size is shown but with several unneeded places after the decimal point (2.267589569092) }
  end;
end;

如您所见,我尝试了几种方法来消除数字。问题是MsgBox 中的FloatToStr 函数,它会自动添加所有数字。如果我为“大小”选择Integer 类型,它仍然显示长数字,但我不能在MsgBox 中使用IntegerIntToStr(什么可以解决问题),因为这里处理的数字太大了我想在点后保留两位小数。

我也尝试将Format 函数放入MsgBox,但我也遇到了“类型不匹配” 错误。

Inno Setup 不支持FloatToStrF

事先使用FloatToStr 转换“大小”并截断它也不起作用,因为编译器会检查“大小”声明为什么类型,并坚持在MsgBox 中再次使用FloatToStr

我不知道如何将这个数字四舍五入。也许一些不同的方法会有所帮助?

期待你的回答!

【问题讨论】:

    标签: decimal inno-setup rounding pascalscript


    【解决方案1】:

    您可以使用Format 函数。

    看看这个例子:

    procedure TestClick(Sender: TObject);
    var
      Size: Extended;
    begin
      Size := 0;
      Size := Size + 1512820736
      Size := Size + 635711488;
      Size := Size + 286273536;
      Size := Size / 1024 / 1024 / 1024; { now all sizes have been added and the number is converted to be displayed GB, not bytes }
      MsgBox(Format('%.2f Gb.', [Size]), mbInformation, MB_OK); 
    end;
    

    我将数据类型从Single 更改为Extended,作为个人选择。

    或者使用这个函数作为一个更智能的选项来根据字节数添加正确的维度:

    const
      KFactor = 1024;
    
    function FormatBytes(const Bytes: Extended): string;
    var
      Amount: Extended;
      Idx: Byte;
      Dms: array[1..5] of string;
      FmtStr: string;
    begin
      Dms[1] := 'B'; Dms[2] := 'KB'; Dms[3] := 'MB'; Dms[4] := 'GB'; Dms[5] := 'TB';
      Amount := Bytes;
      Idx := 1;
      while Amount > (0.9 * KFactor) do
      begin
        Idx := Idx + 1;
        Amount := Amount / KFactor;
      end;
      if Abs(Amount - Trunc(Amount)) < 0.07 then
        FmtStr := '%.0f %s'
      else
        FmtStr := '%.2f %s';
      Result := Format(FmtStr, [Amount, Dms[Idx]]);
    end;
    

    已编辑答案以调整小数位数,以防显示接近精确的 KB/MB/GB/TB 数量。

    【讨论】:

    • 哇,非常感谢!我错误地使用了 Format 函数,但现在它可以工作了!但是我仍然在努力理解第二个函数是如何工作的......请你解释一下好吗?
    • @user1662035 抱歉,我认为代码不言自明。如果您想弄清楚它是如何工作的,您可能需要调试它并逐步运行它。在第一行放置一个断点 (F5),一旦它停止安装程序的执行,您可以继续执行单步 (F8),同时通过将鼠标光标悬停在脚本中的名称上来检查变量值。
    • const KFactor = 1024;我没有注意到它不包括在内。
    • 非常感谢,它有效,我现在明白为什么这个解决方案更好了。祝你有美好的一天:)
    • @user 例如,您也可以将格式字符串设为变量,并将其调整为所需的小数位数。我编辑了我的问题以改进这一点。
    猜你喜欢
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多