高效准确地将货币类型转换为整数

时间:2017-03-17 13:38:38

标签: delphi precision type-conversion

如果可能,我希望避免在类似于以下内容的代码中将Currency转换为Extended(以及可能会丢失精度):

function CurrencyToNumeric(aCurrency: Currency; aScale: Integer): Int64;
const 
  scales: array [-{18}5..-1] of int64 = (100000, 10000, 1000, 100, 10); 
var
  aCurrencyAsInt64: Int64 absolute aCurrency;
begin
  if aScale = -4 then
    Result := aCurrencyAsInt64
  else
    Result := Round(aCurrency * scales[aScale]); // currency -> extended -> integer
end;

这可能吗?

2 个答案:

答案 0 :(得分:3)

我相信你正在寻找这样的功能:

function CurrencyToNumeric(aCurrency: Currency; aScale: Integer): int64;
var
  aCurrencyAsInt64: int64 absolute aCurrency;
  i, factor, rem: Integer;
begin
  if aScale <= -4 then begin
    factor := 1;
    for i := -4 downto aScale+1 do begin
      factor := factor * 10;
    end;
    Result := aCurrencyAsInt64 * factor;
  end else begin
    factor := 1;
    for i := -4 to aScale-1 do begin
      factor := factor * 10;
    end;
    Result := aCurrencyAsInt64 div factor;
    rem := aCurrencyAsInt64 mod factor;
    if rem>=factor div 2 then begin
      inc(Result);
    end;
  end;
end;

这部分代码

if rem>=factor div 2 then begin
  inc(Result);
end;

实施舍入政策。您可能希望做出不同的选择。修改此代码就可以了,应该明白如何去做。

但是,我也不相信问题中的版本被破坏了。你有失败的示例输入吗?另一方面,避免转换为固定点十进制类型的二进制浮点确实感觉合理。现在,如果只有Embarcadero实现了这种类型,而不需要使用浮点运算。

答案 1 :(得分:1)

感谢David的回答,我最终得到了以下实现,这不仅是浮动的,而且比问题中的函数更快。

function CurrencyToNumeric(Value: Currency; Scale: Integer): Int64;
const
  factors: array [-4..-1] of Int64 = (10000, 1000, 100, 10);
var
  factor: Integer;
  ValueAsInt64: Int64 absolute Value;
begin
  if Scale = -4 then
    Result := ValueAsInt64
  else if Scale < -4 then
    Result := ValueAsInt64 * factors[4 + Scale]
  else begin
    factor := factors[-(4 + Scale)];
    Result := ValueAsInt64 div factor;
    if ValueAsInt64 mod factor >= factor div 2 then Inc(Result);
  end;
end;