我将为一家为金融机构编程的公司工作,我将会花很多钱。在此之前,这对我来说并不是一个主要的问题,因为我一直在做小钱的事情而且Double在某些时候已经足够了,但现在甚至1便士也很重要。
我想每个人都可能知道
Dim mValue as Decimal = 100 'seems the best type for now
mValue = mValue / 3
Console.WriteLine(mValue)
Console.ReadLine()
mValue = mValue * 3
Console.WriteLine(mValue)
'Outputs 99.9999999999999999999999999... and never hits 100
那么我怎样才能克服这个问题并找到更好的精确结果呢?
感谢。
答案 0 :(得分:5)
如果你需要能够执行任意分割,听起来你需要一个有理数的表示(一个分数)。我不相信.NET默认提供一个,并且你会“有趣”地以与内置数字类型一样的方式实现它。这可能会让你进行加法,减法,乘法和除法 - 但如果你也需要无理数(例如取平方根),它就无济于事。
你确定你将被除以3吗?你确定你不能舍入(比如)最接近的一分钱1000?您应该了解计算周围的精确要求是什么 - 我怀疑您确实需要无限精确。
答案 1 :(得分:4)
在处理金钱时,你不应该这样分开。您应该尽可能均匀地分配金额,从而获得分配列表,例如:
100 allocated by 3 = [ 33, 33, 34 ]
有人必须得到额外的一分钱。
此外,使用表示便士数的整数比使用十进制数更简单。
而且,封装货币操作是一个专门的类。看看Money pattern。
答案 2 :(得分:3)
你能为我提供一个真实的用例示例吗?
mValue = mValue / 3
在三名银行劫匪之间划分 $ 100 ? 好吧,你不能给每个 $ 33。(3), $ 0.01 仍然必须“无处”(如果你不想让它们互相残杀)。
我只是这样说,因为钱不是数学,你需要确定所需的精度。
不多也不少。
答案 3 :(得分:2)
我不是这个领域的专家,所以有更多经验的人可能会更好地回答这个问题。
您可以非常安全地舍入到10000左右的分数,然后在您想要使用该号码时四舍五入到最近的便士。这适用于您发布的示例
100/3 = 33.333333333333333 * 3 = 99.99999999999,然后四舍五入为100.
我知道许多事情都使用了银行家的四舍五入。这是为了防止当事情以5结尾时赔钱。如果5之前的数字是奇数,则向上舍入,如果数字是偶数则向下舍入。需要考虑的事情。
答案 4 :(得分:0)
重要的是为特定应用程序使用精确定义的舍入规则。如果结算应用程序指定所有订单项金额将四舍五入到最接近的便士,则发票总额应反映该结果。如果它指定所有计算都将执行到百分之一便士,那么发票应该反映出来(可能将小部分硬币格式化为上标,即天然气价格的方式)。在某些情况下,可以持续在发票项目中分配小数便士,例如
old_total = total old_rounded_total = rounded_total total = total + line_item rounded_total = round_to_penny(total) displayed_line_item_cost = rounded_total - old_rounded_total
在其他情况下,可以将所有发票行四舍五入到最近的便士,从该总额中减去所有非圆形发票行的总和,并向上或向下调整最接近“便士”边界的那些行。 / p>
如果舍入语义定义明确,并且应用程序遵循它们,则结果将与规范精确匹配。如果语义没有明确定义,结果也不会。