如何在区块链上计算PMT函数(金融函数)

时间:2018-08-01 14:52:54

标签: blockchain solidity financial

如何转换此代码(javascript代码) 进入坚固的代码,它将起作用吗?

function pmt(rate_per_period, number_of_payments, present_value, future_value){
if(rate_per_period != 0.0){
    // Interest rate exists
    var q = Math.pow(1 + rate_per_period, number_of_payments);
    return (rate_per_period * (future_value + (q * present_value))) / ((q-1) * (1 + rate_per_period ));

} else if(number_of_payments != 0.0){
    // No interest rate, but number of payments exists
    return -(future_value + present_value) / number_of_payments;
}

return 0;}

已执行此功能:

function PMT(uint _rate,uint256 _term,uint _pv) public view returns (uint)
{
     uint q = ((1 + _rate) ** _term);
    return (_rate *  (((1 + _rate) ** _term) * _pv)) / ((((1 + _rate) ** _term)-1) * (1+_rate));
}

,我该如何可靠地表示十进制值? Solidity尚不完全支持定点数。 它们可以声明,但不能分配给它们或从它们分配。

例如功能参数:

pmt(0.0025,12,700000);

*************编辑

乘法功能不起作用

PMT的参数:

  1. 总资金(700000)
  2. totalMonths(12)
  3. totalYears(1)
  4. annualYieldInterest(3%-0.03)

如果我将通过10 ** 2 = 100为它们供电 参数将为

  1. 总资金(70000000)
  2. 总月数(1200)
  3. 总年数(100)
  4. annualYieldInterest(3%-0.03-3)

在我开始计算PMT函数之前,我必须计算他得到的参数:

  1. 总资金:7000万
  2. rate:3/1200-0.0025(通过上面的参数)
  3. totalMonths:12

所以我仍然得到浮点值。

2 个答案:

答案 0 :(得分:0)

您最好的选择是将所有值乘以10的幂,这样您就不再具有浮点数了。然后执行计算,并将结果值除以合同外的10**decimals

这与各种令牌用于跟踪余额的方法相同。

答案 1 :(得分:0)

您可以使用ABDK Math 64.64库。它具有您需要的所有功能(addsubmuldivnegpow),并且使用定点数进行操作。请注意,它使用二进制而不是十进制固定点,点后有64个二进制数字。因此,为了将十进制数转换为二进制定点,您基本上需要将其乘以2 ^ 64。要从定点转换为小数,只需除以2 ^ 64。

使用该库,您的Javascript函数可能会这样移植到Solidity:

function pmt (
  int128 rate_per_period, int128 number_of_payments,
  int128 present_value, int128 future_value) public pure returns (int128) {
  if (rate_per_period != 0) {
    // Interest rate exists
    int128 q =
      ABDKMath64x64.pow (
        ABDKMath64x64.add (
          0x10000000000000000,
          rate_per_period),
        ABDKMath64x64.toUInt (
          number_of_payments));
    return
      ABDKMath64x64.div (
        ABDKMath64x64.mul (
          rate_per_period,
          ABDKMath64x64.add (
            future_value,
            ABDKMath64x64.mul (
              q,
              present_value))),
        ABDKMath64x64.mul (
          ABDKMath64x64.sub (
            q,
            0x10000000000000000),
          ABDKMath64x64.add (
            0x10000000000000000,
            rate_per_period)));
  } else if (number_of_payments != 0) {
    // No interest rate, but number of payments exists
    return
      ABDKMath64x64.div (
        ABDKMath64x64.neg (
          ABDKMath64x64.add (
            future_value,
            present_value)),
        number_of_payments);
  } else return 0;
}

请注意,1变成了0x10000000000000000,即2 ^ 64。在将所有参数传递给此函数之前,您需要将所有参数乘以2 ^ 64,并且在使用结果之前,需要将结果除以2 ^ 64。

我刚刚在Remix中使用以下参数尝试了此Solidity函数:

rate_per_period = 0.03    // = 0x7AE147AE147AE14 / 2^64
number_of_payments = 10.0 // = 0xA0000000000000000 / 2^64
present_value = 1.0       // = 0x10000000000000000 / 2^64
future_value = 2.0        // = 0x20000000000000000 / 2^64

它返回了我0.2832= 0x487F82986F5A14DC / 2^64),这与您的Javascript函数针对这些参数返回的结果相同。