Format stones and pounds correctly?

I have a chart used to display weight in Stones and Pounds (lbs).

The chart is filled with data from the record for the weight of the Double data type.

These records are edited at runtime, and I need to know how to format the entered data correctly.

To better understand, first look at these sample values, they are represented as Stones and pounds:

  • 8.09 (8 stones and 9 pounds)
  • 12.03 (12 stones and 3 pounds)
  • 14.16 (14 stones and 16 pounds)
  • 11.13 (11 stones and 13 pounds)
  • 17.14 (17 stones and 14 pounds)

There is only 14 pounds in the stone, so any value entered .13 should increase the value of the stones by 1 and reduce the value of the pound, starting with .00 - so with this in mind, from the above example, these two values ​​are incorrect:

  • 14.16
  • 17.14

they should be:

  • 15.02
  • 18.00

Is there a built-in math function that can correctly format / round stones and pounds correctly?

If it weren’t, it would be very interesting for me to see an answer that shows the logic or method of approach to solving this issue.

I was thinking about checking part of the pounds, and if the value is> 0.13, then I increase the number of stones, but then I'm not sure how best to do this, especially if the value can be about 13.76, then I do not know what to change the stones and pounds (that's where I start to confuse myself).

Thanks in advance.

+4
source share
3 answers

For pounds, you get the fractional part with Frac(weight) , and then multiply by 100. Then use Round to get it in integer form:

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

And for stones, it's just Trunc :

 stones := Trunc(weight); 

In the other direction:

 weight := stones + pounds/100.0; 

With these features, you can easily do the rest. The validity of checking pounds is greater than 14, which are easy to handle. For instance:

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

I would be very surprised if you could find this code anywhere in the general purpose library. This is because it is a very poor way to store weight. If you are going to use a floating point format, you should do it like this:

 weight := stones + pounds/14.0; 

In the other direction, you will do it as follows:

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

Unfortunately, you still need to shuffle the div / mod. Imagine what happens when weight=9.99 , for example.

Performing this method makes arithmetic of floating point values ​​more reasonable. For example, suppose you measure 10 people and want to know the total. It makes sense to do this with a true floating point representation, but not with your representation.

To see this, suppose these 10 people, and they all weigh zero stones, 10 pounds. Very small people I know. But you would call it 0.1. Add 10 lots, and the weight is 1.0. But it is clear that the actual value is 100 pounds, or 7 stone two pounds.

But if you take 10 pounds and feed them:

 weight := stones + pounds/14.0; 

then you will find the weight value 10/14. Add 10 lots to get 100/14, and well, I'm sure you will get my drift!

Another obvious way to store such data is in pounds. Either integers or a floating point can make sense.

+5
source

Or you CAN DO something like this :-)

 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. 

That will allow you to do things like this

 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. 

which outputs this:

 1 stone and 5 pounds 3 stones and 12 pounds 5 stones and 3 pounds 
+4
source
 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; 
+1
source

All Articles