UFN_CURRENCY_CONVERTBYPROPORTION
Converts an amount from one currency to another using the total amounts in both currencies.
Return
Return Type |
---|
money |
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@AMOUNT | money | IN | |
@FULLAMOUNT | money | IN | |
@FULLAMOUNTTOCURRENCY | money | IN | |
@DECIMALDIGITSTOCURRENCY | tinyint | IN |
Definition
Copy
CREATE function dbo.UFN_CURRENCY_CONVERTBYPROPORTION
(
@AMOUNT money,
@FULLAMOUNT money,
@FULLAMOUNTTOCURRENCY money,
@DECIMALDIGITSTOCURRENCY tinyint
)
returns money
as begin
--TODO: We could probably expand the limits but it would require more testing to find possible overflows.
--TODO: We could probably allow negative amounts and negative full amounts but it would require more testing to find possible overflows.
if @AMOUNT < 0 or @FULLAMOUNT < 0
return 0;
if @AMOUNT >= @FULLAMOUNT
return @FULLAMOUNTTOCURRENCY;
--Caution! Performing decimal math is tricky. The basic formula for @AMOUNTCONVERTED is:
-- (@AMOUNT / @FULLAMOUNT * @FULLAMOUNTTOCURRENCY)
-- Money fits into a decimal(19,4). Computing the amount converted percent
-- is decimal(19,4) / decimal(19,4) = decimal(38,19). From the rule that 0 <= @AMOUNT <= @FULLAMOUNT, we
-- know this number must be between 0 and 1 so we can reduce its precision. We convert it to
-- decimal(22,19) so that we can multiply by @FULLAMOUNTCONVERTED without losing precision:
-- decimal(22,19) * decimal(19,4) = decimal(38,19). Rounding to the decimal digits of the currency
-- prevents results with fractions of pennies or fractions of yen; rounding yields smoother distributions
-- than truncating. Finally, converting back to money removes the extra scale.
declare @AMOUNTCONVERTEDPERCENT decimal(38,19);
declare @AMOUNTCONVERTEDFULLPRECISION decimal(38,19);
declare @AMOUNTCONVERTED money;
set @AMOUNTCONVERTEDPERCENT = (convert(decimal(19,4),(@AMOUNT)) / convert(decimal(19,4),@FULLAMOUNT));
set @AMOUNTCONVERTEDFULLPRECISION = (convert(decimal(22,19),@AMOUNTCONVERTEDPERCENT) * convert(decimal(19,4),@FULLAMOUNTTOCURRENCY));
set @AMOUNTCONVERTED = convert(money, round(@AMOUNTCONVERTEDFULLPRECISION, @DECIMALDIGITSTOCURRENCY, 0));
if @AMOUNTCONVERTED > @FULLAMOUNTTOCURRENCY
set @AMOUNTCONVERTED = @FULLAMOUNTTOCURRENCY;
return @AMOUNTCONVERTED;
end