减去直到达到期望值

时间:2012-10-17 05:52:24

标签: delphi math

早上好。

我目前正试图找出一些我自信足够简单的事情,但事实证明这是一项任务和一半的实际工作。

我正在开发一个旨在通过在其他地方重新定位各种文件来最小化驱动器使用的项目。我有一个数组(0..12)的int64值,其中包含我可能想要移动的文件的文件大小。该阵列的排序方式是预测的最大文件大小,直至预测的最小文件大小。我还将这些文件的名称存储在不同的数组中(称为WoWData,也称为[0..12])。然后我得到了“安装尺寸”和“所需尺寸”。

我的任务是计算我需要移动哪些文件,以便通过浏览文件大小数组将“安装大小”降低到“所需大小”,并将值从安装大小中取出,直到我达到< =所需的大小。

这是我一直在尝试使用的一些示例代码(Delphi / Firemonkey)。我试图弄清楚如何完成这样的任务让我感到困惑,因此毫无疑问会有很多问题;

Global Vars;
    _WoWDataFileSize : Array [0..12] of Int64;
    // "TBWoWDir" is a TTrackBar (Firemonkey)

var
  TotalSize, ReqSize, DiffSize, CurDiff : Int64;
  i : Integer;
begin
  // Set up initial values to work with
  ReqSize := Round(TBWoWDir.Value); // Requested Size
  TotalSize := Round(TBWoWDir.Max); // Actual installation size
  CurDiff := 0; // Assume as "Current Difference in size"

  // Calculate difference between install and requested size
  DiffSize := TotalSize - ReqSize; // This calculates correctly

// The below is what i'm struggling with
  repeat
    for i := Low(_WoWDataFileSize) to High(_WoWDataFileSize) do
      begin
        CurDiff := ReqSize - _WoWDataFileSize[i];
      end;
  until CurDiff <= ReqSize;
end;

我确实尝试使用没有repeat .. until循环的for循环,但是再次尝试解决这个问题时我感到非常困惑。


让我举个例子。假设_WoWDataFileSize[0]为200,_WoWDataFileSize[1]_WoWDataFileSize[12]与数组索引的值相同(例如_WoWDataFileSize[6] = 6,_WoWDataFileSize[8] = 8,等)。

如果我想根据数组计算150的值(200 - 12 - 11 - 10 - 9 - 8Array[0] - Array[12] - Array[11] - Array[10] - Array[9] - Array[8]),并获取我需要移动的文件列表以满足此要求WoWData数组,我将如何编写例程?

150可以替换为任何数字,因为我正朝着TBWoWDir.Value指定的动态用户请求的大小努力。

我想我可能需要进行While循环并使用i := i+1设置。实际上,我可以通过并对其进行硬编码,以便一次取出数组中的一个值并每次检查我是否&lt; =期望值 - 每个项目为2-3行(所以总共24-36行),但这既维修又不理想。我很想知道如何在循环中完成它。我通常没有循环问题,但这对我来说几乎不是标准的。

3 个答案:

答案 0 :(得分:1)

curdiff:= 0;
i:= Low(_WoWDataFileSize) - 1;
while (curdiff <= reqsize) and (i < High(_WoWDataFileSize)) do
 begin
  inc (i);
  curdiff:= curdiff + _WoWDataFileSize[i];
 end;

在循环结束时,要么已达到所需的缩小尺寸,要么已遍历整个阵列。

答案 1 :(得分:1)

恕我直言,你的代码中缺少两行:o)

CurDiff := ReqSize;
// repeat
  for i := Low(_WoWDataFileSize) to High(_WoWDataFileSize) do
    begin
      CurDiff := CurrDiff - _WoWDataFileSize[i];
      if CurDiff <= ReqSize then break; // breaks the for..to loop
    end;
// until CurDiff <= ReqSize;

编辑无需重复...直到循环

但恕我直言,仅仅计算尺寸而不存储哪些文件匹配并不是很有用。 因此,使用CustomObject和Lists(thanx to Generics)将非常简单:

type
  TFileObject = class
  private
    FName : string;
    FSize : Int64;
  public
    constructor Create( AName : string; ASize : Int64 );
  published
    property Name : string read FName;
    property Size : Int64 read FSize;
  end;

procedure MoveFileObject(AMaxSize : Int64; ASrcList, ATarList : TList<TFileObject> );
var
  LItem : TFileObject;
  LSize : Int64;
begin
  LSize := 0;
  for LItem in ASrcList do
  begin
    if LSize + LItem.Size <= AMaxSize then
      begin
        LSize := LSize + LItem.Size;
        ATarList.Add( LItem );
      end;
  end;
end;

答案 2 :(得分:0)

感谢大家的回答,我想出了我的错误。当我在我最初的问题中计算时,我忘了考虑我对价值的划分(为了显示MB而不是字节,因为TBWoWDir.Value是实时绑定到TLabel.text,但实际上在分配TBWoWDir.Max)之前,大小正在被划分。

感谢No'am Newman回答的一些调整,我设法自己解决了这个问题。以下是我得到的结果(或更接近它);

Global Vars;
    _WoWDataFileSize : Array [0..12] of Int64;
Global Const;
    _WoWData : Array [0..12] of String;
    // "TBWoWDir" is a TTrackBar (Firemonkey)

[...]
var
  ReqSize : int64;
  DiffSize, CurDiff : Int64;
  i, ii : Integer;
  FilesTot : Integer;
  FILESMSG : String;
begin
  // Set up initial values to work with
  ReqSize := Round(TBWoWDir.Value) * 1024 * 1024; // Requested Size - Multiplied from formatting
  TotalSize := Round(TBWoWDir.Max) * 1024 * 1024; // Actual installation size - Multiplied from formatting

  DiffSize := TotalSize - ReqSize; // Calculate Difference
  CurDiff := 0; // Reset Current Difference
  i := -1; // Reset i
  repeat
    inc (i); // Increment i
    CurDiff := CurDiff + _WoWDataFileSize[i]; // Add current array item file size to CurDiff
  until (CurDiff >= (DiffSize)) or (i >= 12); // Repeat until we reach ideal size or the end of the array

  // Calculate which array item we stopped at
  for ii := 0 to i do // use i from previous loop as the max
  begin
    FILESMSG := FILESMSG + 'File: ' + WoWData[ii] +
                           ' | Size: ' + IntToStr(_WoWDataFileSize[ii])+' '#13#10;
    FilesTot := FilesTot + _WoWDataFileSize[ii];
  end;

  // Show Message providing details
  ShowMessage('CurDiff:' + IntToStr(CurDiff div 1024 div 1024) +
              ' | DiffSize: ' + IntToStr(DiffSize div 1024 div 1024) +
              ' | Array i: ' +
              IntToStr(i) +#13#10+
              'Difference between CurDiff and DiffSize: '+ IntToStr(((DiffSize div 1024 div 1024) - (CurDiff div 1024 div 1024)))+#13#10#13#10+
              'File Details' +#13#10#13#10+
              FilesMsg +#13#10#13#10+
              'Total Size: ' + IntToStr(FilesTot));
end;

代码在那里告诉我需要复制哪些文件(因此现在修改它以复制文件并不太困难),整个ShowMessage用于自我证明(因为我使用) ShowMessage在开发期间我需要验证值是否正确返回,因为我确信其他人也会这样做。)