4

我有一个图表,用于以石头和磅(磅)显示重量。

该图表由记录中的数据填充,对于权重,数据类型为 Double。

记录数据是在运行时编辑的,我需要知道一种正确格式化输入数据的方法。

为了更好地理解,首先看一下这些样本值,它们表示为 Stones 和 lbs:

  • 8.09(8 石头和 9 磅)
  • 12.03(12 石头和 3 磅)
  • 14.16(14 石头和 16 磅)
  • 11.13(11 石头和 13 磅)
  • 17.14(17 石头和 14 磅)

一块石头只有 14 磅,因此输入的任何超过 0.13 的值都应将石头值增加 1 并从 0.00 开始降低磅值 - 因此请记住,从上面的示例中,这些值中的两个不正确:

  • 14.16
  • 17.14

他们应该是:

  • 15.02
  • 18.00

是否有一个内置的数学函数可以正确格式化/圆形石头和磅?

如果不是,我真的很想看到一个显示解决这个问题的逻辑或方法的答案。

我想检查磅部分,如果值 > 0.13 然后我增加石头,但是我不确定如何最好地做到这一点,特别是如果值可能是 13.76 那么我不知道要改变什么石头和重击(这是我开始混淆自己的地方)。

提前致谢。

4

3 回答 3

5

对于磅,您得到小数部分,Frac(weight)然后乘以 100。然后使用Round以整数形式得到它:

pounds := Round(100*Frac(weight));

而对于石头来说,它只是Trunc

stones := Trunc(weight);

在另一个方向你做:

weight := stones + pounds/100.0;

使用这些功能,您可以轻松完成剩下的工作。对大于 14 磅值的有效性检查很容易处理。例如:

stones := Trunc(weight);
pounds := Round(100*Frac(weight));
stones := stones + pounds div 14;
pounds := pounds mod 14;

如果您在通用库中的任何地方找到此代码,我会感到非常惊讶。那是因为这是一种非常糟糕的体重储存方式。如果您要使用浮点格式,您应该这样做:

weight := stones + pounds/14.0;

在另一个方向,你会这样做:

stones := Trunc(weight);
pounds := Round(14*Frac(weight));
stones := stones + pounds div 14;
pounds := pounds mod 14;

不幸的是,你仍然需要做 div/mod shuffle。例如,想象一下当 时会发生什么weight=9.99

这样做会使浮点值的算术更明智。例如,假设您测量了 10 个人的体重并想知道总数。用真正的浮点表示来做到这一点是有意义的,但不是用你的表示。

要看到这一点,假设这 10 个人,他们都重 0 石头,10 磅。我认识的人很小。但你会称之为 0.1。将其中的 10 批相加,您的权重为 1.0。但很明显,实际价值是 100 磅,即 7 石两磅。

但是,如果您将 10 磅的体重喂入:

weight := stones + pounds/14.0;

然后你会发现权重值为 10/14。添加 10 批得到 100/14,好吧,我相信你明白我的意思!

存储此类数据的另一种明显方式是磅。整数或浮点数都有意义。

于 2013-03-18T18:12:31.293 回答
4

或者你可以做这样的事情:-)

unit PoundsAndStones;

interface

uses
  SysUtils;

type
  TPoundStone = record
  private
    FWeight : double;
    function GetPounds: integer;
    procedure SetPounds(const Value: integer);
    function GetStones: integer;
    procedure SetStones(const Value: integer);
    procedure SetWeight(const Value: double);
    function GetString: string;
  public
    property Weight : double read FWeight write SetWeight;   //Weight in stones.pounds format
    property Stones : integer read GetStones write SetStones; //Weight in stones, fraction part ignored
    property Pounds : integer read GetPounds write SetPounds; //Weight in pounds
    property AsString : string read GetString;

    class operator Implicit(A : double) : TPoundStone;
    class operator Implicit(A : TPoundStone) : double;
    class operator Add(A, B: TPoundStone): TPoundStone;
  end;

implementation

class operator TPoundStone.Add(A, B: TPoundStone): TPoundStone;
begin
  Result.Weight := A.Weight + B.Weight;
end;

function TPoundStone.GetPounds: integer;
begin
  Result := round(frac(FWeight)*100);
end;

function TPoundStone.GetStones: integer;
begin
  Result := trunc(FWeight);
end;

function TPoundStone.GetString: string;
var
  P,S : string;
begin
  if Stones > 1 then
    S := inttostr(Stones)+' stones'
  else if Stones = 1 then
    S := '1 stone'
  else
    S := '';

  if Pounds > 1 then
    P := inttostr(Pounds)+' pounds'
  else if Pounds = 1 then
    P := '1 pound'
  else
    P := '';

  if (P > '') and (S > '') then
    Result := S + ' and ' + P
  else
    Result := S + P;
end;

class operator TPoundStone.Implicit(A: double): TPoundStone;
begin
  Result.FWeight := A;
end;

class operator TPoundStone.Implicit(A: TPoundStone): double;
begin
  Result := A.FWeight;
end;

procedure TPoundStone.SetWeight(const Value : double);
var
  P,S : integer;
begin
  S := trunc(Value);
  P := round(100*frac(Value));

  S := S + P div 14;
  P := P mod 14;

  FWeight := S + P/100.0;
end;

procedure TPoundStone.SetPounds(const Value: integer);
var
  P,S : integer;
begin
  S := Value div 14;
  P := Value mod 14;

  FWeight := S + P/100.0;
end;

procedure TPoundStone.SetStones(const Value: integer);
begin
  Weight := Value*14;
end;

end.

这将允许你做这样的事情

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  PoundsAndStones in 'PoundsAndStones.pas';

var
  P0,P1,P2 : TPoundStone;

begin
  P0 := 1.05;
  P1 := 3.12;

  writeln(P0.AsString);
  writeln(P1.AsString);

  P2 := P0 + P1;
  writeln(P2.AsString);
end.

这将输出:

1 stone and 5 pounds
3 stones and 12 pounds
5 stones and 3 pounds
于 2013-03-18T19:47:20.750 回答
1
function tostonesandpounds(p_value : double) : double;
var
  stone : integer;
  pounds : integer;
begin
  stone := trunc(p_value);
  pounds := trunc(100.0*(p_value + 0.009));
  pounds := pounds-(stone*100);
  inc(stone,(pounds div 14));
  pounds := pounds mod 14;
  result := stone + (pounds/100.0);
end;
于 2013-03-18T18:46:23.390 回答