正确格式化石头和磅?

时间:2013-03-18 17:58:53

标签: delphi math delphi-xe type-conversion

我有一张图表用于显示石头和磅(磅)的重量。

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

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

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

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

一块石头只有14磅,所以输入的任何值都超过.13应该将石头值增加1并从.00开始降低磅值 - 所以考虑到这一点,从上面的样本2这些值不正确:

  • 14.16
  • 17.14

他们应该是:

  • 15.02
  • 18.00

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

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

我想到检查磅部分,如果值> gt; 0.13然后我增加了石头,但是后来我不知道如何最好地做到这一点,如果价值可能是13.76那么我就不知道要把石头和磅改成什么(这是我开始混淆的地方自己)。

提前致谢。

3 个答案:

答案 0 :(得分: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个人,他们都是零石头,10磅。我认识的人很小。但你会称之为0.1。加10批,你的重量为1.0。但很明显,实际值是100磅,或7石2磅。

但如果你服用10磅并喂它:

weight := stones + pounds/14.0;

然后你会发现重量值为10/14。添加10个,以获得100/14,好吧,我相信你会得到我的漂移!

存储此类数据的另一种显而易见的方法是磅。整数或浮点都有意义。

答案 1 :(得分: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

答案 2 :(得分: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;