Reputation: 2596
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
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
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