用Ruby做BigDecimal会计。我何时可以转换为浮动?

时间:2018-01-31 21:07:05

标签: ruby floating-point

我基本上想知道最好将我的BigDecimal数字转换为可读格式(也许是float),以便将它们显示给客户端:

为了计算负债,我做贡献 - 来自每个地址的分配。

例如,如果一个人向一个地址提供2个单位,并且该地址将1个单位分配给该人,那么仍然有1个单位的责任。这就是下面发生的事情。这些数字都是加密货币的单位。

这是另一个例子:

address1address2分别为address3贡献2个硬币,address3address1分配1.0个硬币,向address2分发0.5个硬币,然后address3address1承担1.0硬币负债,对address2承担1.5硬币负债。

所以下面使用BigDecimal的实际数据:

contributions = 
{"1444"=>#<BigDecimal:7f915c08f030,'0.502569E2',18(36)>,
"alice"=>#<BigDecimal:7f915c084018,'0.211E1',18(27)>,
 "address1"=>#<BigDecimal:7f915c0a4430,'0.87161E1',18(36)>,
 "address2"=>#<BigDecimal:7f915c0943f0,'0.84811E1',18(36)>,
 "address3"=>#<BigDecimal:7f915c0a43e0,'0.385E0',9(18)>,
 "address6"=>#<BigDecimal:7f915c09ebe8,'0.1E1',9(18)>,
 "address7"=>#<BigDecimal:7f915c09eb98,'0.1E1',9(18)>,
 "address8"=>#<BigDecimal:7f915c09d428,'0.15E1',18(18)>,
 "address9"=>#<BigDecimal:7f915c09d3d8,'0.15E1',18(18)>,
 "address10"=>#<BigDecimal:7f915c0a7540,'0.132E1',18(36)>,
 "address11"=>#<BigDecimal:7f915c0af8a8,'0.392E1',18(36)>,
 "address12"=>#<BigDecimal:7f915c0a4980,'0.14E1',18(36)>,
 "address13"=>#<BigDecimal:7f915c0af858,'0.2133333333 3333333333 33333334E1',36(54)>,
 "address14"=>#<BigDecimal:7f915c0a54c0,'0.3533333333 3333333333 33333334E1',36(45)>,
 "address15"=>#<BigDecimal:7f915c0a66e0,'0.1533333333 3333333333 33333334E1',36(36)>,
 "sdfds"=>#<BigDecimal:7f915c0a6118,'0.1E0',9(27)>,
 "sf"=>#<BigDecimal:7f915c0a6028,'0.1E0',9(27)>,
 "address20"=>#<BigDecimal:7f915c0ae688,'0.3E0',9(18)>,
 "address21"=>#<BigDecimal:7f915c0ae638,'0.3E0',9(18)>,
 "address23"=>#<BigDecimal:7f915c0ae070,'0.1E0',9(27)>,
 "address22"=>#<BigDecimal:7f915c0adf80,'0.1E0',9(27)>,
 "add1"=>#<BigDecimal:7f915c0ad328,'0.1E0',9(18)>,
 "add2"=>#<BigDecimal:7f915c0ad2d8,'0.1E0',9(18)>,
 "addx"=>#<BigDecimal:7f915c0acd10,'0.1E0',9(27)>,
 "addy"=>#<BigDecimal:7f915c0acc20,'0.1E0',9(27)>}

和发行版:

distributions = 
 {"1444"=>#<BigDecimal:7f915a9068f0,'0.502569E2',18(63)>,
 "alice"=>#<BigDecimal:7f915a8f44e8,'0.211E1',18(27)>,
 "address1"=>#<BigDecimal:7f915a906800,'0.87161E1',18(54)>,
 "address2"=>#<BigDecimal:7f915a906710,'0.84811E1',18(54)>,
 "address3"=>#<BigDecimal:7f915a906620,'0.385E0',9(36)>,
 "address6"=>#<BigDecimal:7f915a8fdea8,'0.1E1',9(27)>,
 "address7"=>#<BigDecimal:7f915a8fddb8,'0.1E1',9(27)>,
 "address8"=>#<BigDecimal:7f915a8fd5e8,'0.15E1',18(18)>,
 "address9"=>#<BigDecimal:7f915a8fd4f8,'0.15E1',18(18)>,
 "address10"=>#<BigDecimal:7f915a8fc9b8,'0.132E1',18(36)>,
 "address11"=>#<BigDecimal:7f915a9071b0,'0.3920000000 0000003E1',27(45)>,
 "address12"=>#<BigDecimal:7f915a907660,'0.1400000000 0000001E1',27(36)>,
 "address13"=>#<BigDecimal:7f915a9070c0,'0.2133333333 3333337E1',27(45)>,
 "address14"=>#<BigDecimal:7f915a906530,'0.3533333333 3333333333 33333334E1',36(54)>,
 "address15"=>#<BigDecimal:7f915a8fc148,'0.1533333333 3333334E1',27(27)>,
 "sdfds"=>#<BigDecimal:7f915a907f98,'0.1E0',9(27)>,
 "sf"=>#<BigDecimal:7f915a907e08,'0.1E0',9(27)>,
 "address20"=>#<BigDecimal:7f915a906ad0,'0.3000000000 0000003E0',18(27)>,
 "address21"=>#<BigDecimal:7f915a9069e0,'0.3000000000 0000003E0',18(27)>,
 "address23"=>#<BigDecimal:7f915a9063c8,'0.1E0',9(27)>,
 "address22"=>#<BigDecimal:7f915a906238,'0.1E0',9(27)>,
 "add1"=>#<BigDecimal:7f915a9060a8,'0.5E-1',9(27)>,
 "add2"=>#<BigDecimal:7f915a905f18,'0.1E0',9(27)>}

理想情况下,我希望我的责任看起来像这样:

{"add1"=>0.05,
"addx"=>0.1>,
"addy"=>0.1>}

但他们看起来像这样:

{"1444"=>0.0,
 "alice"=>0.0,
 "address1"=>0.0,
 "address2"=>0.0,
 "address3"=>0.0,
 "address6"=>0.0,
 "address7"=>0.0,
 "address8"=>0.0,
 "address9"=>0.0,
 "address10"=>0.0,
 "address11"=>-3.0e-16,
 "address12"=>-1.0e-16,
 "address13"=>-3.66666666666e-16,
 "address14"=>0.0,
 "address15"=>-6.6666666666e-17,
 "sdfds"=>0.0,
 "sf"=>0.0,
 "address20"=>-3.0e-17,
 "address21"=>-3.0e-17,
 "address23"=>0.0,
 "address22"=>0.0,
 "add1"=>0.05,
 "add2"=>0.0,
 "addx"=>#<BigDecimal:7f915c0acd10,'0.1E0',9(27)>,
 "addy"=>#<BigDecimal:7f915c0acc20,'0.1E0',9(27)>}

我不想包含-3.66666666666e-16,因为它基本上是0,甚至Ruby在运行-3.66666666666e-16 > 0时也会以这种方式解释它......它返回false

这就是我的......是一种更好的方式吗?下面的代码是通过从con中减去dis并仅选择大于0.0的负债来计算负债...这对我来说是有意义的,它不包括一次性的硬币授予(必须作为一种责任的匹配贡献)。然后,我将所有内容转换为浮点数,因此它是可读的。这看起来不错吗?

liab = @contributions.merge(@distributions) do |key, con, dis|
      (con - dis)
    end.select { |addr, amount| amount > 0.0 && @contributions.keys.include?(addr) }

    liab.merge(liab) do |k, old, new|
      k = new.to_f
    end

我希望以浮动格式返回的金额,而不是大的十进制对象。我正在做什么好吗?如果我最后转换为浮动,我会保持准确性吗?

0 个答案:

没有答案