delphidouble

Convert Currency amount to cents without going through floating point


Consider this function:

function DollarsToCents(dollars: Currency): Integer;
begin
  result := Trunc(dollars * 100);
end;

The expression dollars * 100 will get converted to an Extended, I believe, which is a binary floating point type, and as a general rule money should not be put into binary floating point due to the possibility of "representation error".

So, my question is: is this code safe? In our case we have no fractional cents, and a typical input to the function might be something like 1.23.

Or is there a better way to do it?


Solution

  • Currency is internally a 64-bit integer expressed in units of 0,01 cents, so $1.00 = 10000 Currency. Taking advantage of this knowledge, you can do it this way:

    function DollarsToCents(dollars: currency): integer;
      var 
        I64 : Int64 ABSOLUTE dollars;
    
      begin
        Result:=I64 DIV 100;
      end;
    

    The ABSOLUTE keyword overlays the I64 variable on top of the dollars parameter, so you can access it as the underlying 64-bit integer.