Anton Duzenko
Anton Duzenko

Reputation: 2596

Limit total currency digits in Format()

I have a limited 80-mm printer output and I need to squeeze a currency in 3 digits. E.g.

2.345 -> 2.3
50.345 -> 50 or 50.

Is it possible with Format()/FormatFloat?

I tried Format('%s%*f', [CurrencyString, 6 - Length(CurrencyString), Ratio]) but it just puts 2 decimals after the separator. CurrencyString is three-char long in my case.

Upvotes: 0

Views: 227

Answers (2)

BigBother
BigBother

Reputation: 367

You can follow this approach:

  uses
    SysUtils, Math;

  function CurrencyTo80MM(const ACurrency: currency): string;
  const
    RoundFactor = 100; //As we have 2 significative decimal digits
  var
    Digits: integer;
  begin
    Digits := Length(IntToStr(Trunc(ACurrency)));
    //Taking into account decimal point if it's the last char
    if Digits = 2
      then Inc(Digits);
    Result := Copy(FormatFloat('#.00', RoundTo(ACurrency * RoundFactor, Digits - 1) / RoundFactor), 1, 3);
  end;

The core of solution is the use of RoundTo() and the use of a "supersampling" to solve rounding error and take into consideration integer part lenght to output fixed length result.

Tested with values:

  2.345 =>  2.3
 50.345 =>  50.
 50.9   =>  51.
  0.123 =>  .12
  0.127 =>  .13
240.1   =>  240
240.6   =>  241

This solution has, imho, the advantage of fixed length (always 3) and maximization of visible value (omitting initial zero).

Upvotes: 0

LU RD
LU RD

Reputation: 34899

It is possible to limit the output by using the width and precision specifiers in Format().

uses
  SysUtils,Math;
var
  ratio : Currency;
  s : String;
begin
  ratio := 2.345;
  s := Format('%3.*f',[Math.IfThen((ratio<9.95) and (ratio>=0),1,0),ratio]);
  WriteLn(s);
  ratio := 50.345;
  s := Format('%3.*f',[Math.IfThen((ratio<9.95) and (ratio>=0),1,0),ratio]);
  WriteLn(s);
end.

Outputs:

2.3
 50

Math.IfThen() is a function that mimics an if-then-else expression.

Upvotes: 2

Related Questions