如何在julia lang中存储货币值并格式化其输出?

如何在julia lang中存储货币值并格式化其输出?,julia,Julia,目前,我正在以::Float64类型存储货币金额,大部分金额以不同的货币单位表示,从数十亿到数亿不等。在其他使用案例中,我也认为货币值必须保持在一个货币单位的数万中,例如0.7564 然而,考虑到与双精度浮点数相关的舍入误差,我是否应该将所有内容转换为定点整数以存储货币单位 其次,如何格式化货币单位的字符串输出,并允许显示相关的货币符号 其次,他们的软件包是否提供了安全使用的“货币”数据类型?以下是存储和显示货币的基本出发点: immutable Currency symbol::Symbo

目前,我正在以
::Float64
类型存储货币金额,大部分金额以不同的货币单位表示,从数十亿到数亿不等。在其他使用案例中,我也认为货币值必须保持在一个货币单位的数万中,例如0.7564

然而,考虑到与双精度浮点数相关的舍入误差,我是否应该将所有内容转换为定点整数以存储货币单位

其次,如何格式化货币单位的字符串输出,并允许显示相关的货币符号


其次,他们的软件包是否提供了安全使用的“货币”数据类型?

以下是存储和显示货币的基本出发点:

immutable Currency
  symbol::Symbol
  amount::Int
end

function Base.show(io::IO, c::Currency)
  print(io, c.symbol, c.amount/100)
end

Currency(:£, 1275) #=> £12.75
这会将货币存储为精确的便士值,因此不会出现舍入错误,但会以通常的方式显示。当然,您可以轻松地对要存储的小数位数进行参数化。我不能回答你是否应该使用像这样的定点数字,但它们肯定会更准确地用于加法、减法和乘法


就现有技术而言,一个快速搜索“currency.jl”的google出现了——它看起来已经过时了,但可能会用作参考。

您绝对不应该使用浮点数作为货币-您应该定义自己的定点数字类型,并使用它。Julia手册在关于转换和升级的章节中有一个关于定义新数字类型的好教程

让我们假设你只需要小数点后的两位数——更不用说英镑、先令和便士了。你的新型号看起来像

immutable Monetary <: Number
    hundredths :: Int64
end

Monetary(ones :: Int64, hundredths :: Int64) = Monetary(hundredths + 100 * ones)
您还希望能够添加和减去它们:

+(x :: Monetary, y :: Monetary) = Monetary(x.hundredths + y.hundredths)
-(x :: Monetary, y :: Monetary) = Monetary(x.hundredths - y.hundredths)
另一方面,你永远不会想把它们相乘,但是把一个货币总额乘以一个整数就可以了:

*(x :: Bool, y :: Monetary) = ifelse(x, y, Monetary(0))
*(x :: Monetary, y :: Bool) = ifelse(y, x, Monetary(0))
*(x :: Integer, y :: Monetary) = Monetary(x * y.hundredths)
*(x :: Monetary, y :: Integer) = Monetary(x.hundredths * y)
最后,如果在表达式中混合整数和货币总和,则可以将所有内容转换为货币值:

Base.convert(::Type{Monetary}, x :: Int64) = Monetary(x, 0)
Base.promote_rule(::Type{Monetary}, ::Type{Int64}) = Monetary
这足以执行有用的计算:

julia> Scrooge.Monetary(30,5) * 3 + 12
102.15
但将可靠地捕获不正确的操作:

julia> Scrooge.Monetary(30,5) * 3.5
ERROR: no promotion exists for Monetary and Float64
 in * at ./promotion.jl:159
提供用于处理货币的界面:

using Currencies
@usingcurrencies USD
format(1.23USD + 4.56USD, styles=[:us, :brief])  # $5.79
它支持类型安全算法、货币转换和灵活的打印


免责声明:我是currency.jl.的维护者。

我认为这是目前最好的方法,我认为我还没有看到一个包含currency pretty printing/math的软件包。我想把
amount::Int
中的
Int
换成其中一种类型。这绝对是一个很好的建议——这可以为货币类型节省大量重载算术等的时间。使用上面答案中没有显示的
FixedPointNumbers
有什么好处?抽象
Int
的运算符是否足够?在大多数情况下,这不太重要,因为货币相乘没有多大意义。但您必须覆盖某些行为(例如,如上所述的打印),FPN将免费为您提供这些行为。感谢您的关注
using Currencies
@usingcurrencies USD
format(1.23USD + 4.56USD, styles=[:us, :brief])  # $5.79