如果可能,我希望避免在类似于以下内容的代码中将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;
这可能吗?
答案 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;