The # symbol is an optional digit, i.e. it will be used if the digit appearing at this place is not a trailing (or leading) zero. The symbol '0', on the other hand, will always be replaced by a digit, even if it is a trailing or leading zero.
Example:
FormatFloat('0.000', 0.12) --> '0.120' // a '0' is added because the format string dictates 3 decimal places
FormatFloat(0.###', 0.12) --> '0.12' // the '0' is not added because the format string has a '#' here.
or more complex:
FormatFloat('0.00###', 12.3456789) --> '12.34568'
FormatFloat('0.00###', 12.3) --> '12.30'
The # symbol is neglected if it occurs before the decimal separator. If you want to have thousand separators (i.e. grouping of three digits), it is only important to write a comma (,) in front of the decimal separator symbol (.). Buf for better readability, often * symbols are used here as well
Example
FormatFloat('0.0', 1234.5678) --> '1234.6'
FormatFloat('#,##0.0', 1234.5678) --> '1,234.6'
FormatFloat(',0.0', 1234.5678) --> '1,234.6'
FormatFloat('0,000.0', 1.23) --> '0,001.2'
Decimal and thousand separator symbols (. and , respectively) are replaced by the characters defined in the FormatSettings - this, in turn, depends on your language settings. If you are in Europe, often the decimalseparator and thousand separator are interchanged.
If you are in such a country, but want to read/write files in which the default separators are used, you must define your local formatsettings and use this as a parameter of the FormatFloat function:
var
fs: TFormatSettings;
x: Double;
begin
fs.DecimalSeparator := '.';
fs.ThousandSeparator := ',';
WriteLn(FormatFloat('#,##0.0', 1234.5678, fs);
x := StrToFloat('1.2', fs)