我有一张图表用于显示石头和磅(磅)的重量。
图表由记录中的数据填充,对于权重,数据类型为Double。
记录数据在运行时编辑,我需要知道一种正确格式化输入数据的方法。
为了更好地理解,首先看一下这些样本值,它们表示为Stones和lbs:
一块石头只有14磅,所以输入的任何值都超过.13应该将石头值增加1并从.00开始降低磅值 - 所以考虑到这一点,从上面的样本2这些值不正确:
他们应该是:
是否有内置的数学函数可以正确地格式化/圆形石块和磅数?
如果不是,我真的很想看到一个答案,显示解决这个问题的方法的逻辑或方法。
我想到检查磅部分,如果值> gt; 0.13然后我增加了石头,但是后来我不知道如何最好地做到这一点,如果价值可能是13.76那么我就不知道要把石头和磅改成什么(这是我开始混淆的地方自己)。
提前致谢。
答案 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;