为了账号安全,请及时绑定邮箱和手机立即绑定

如何用C表示货币或金钱

如何用C表示货币或金钱

C
宝慕林4294392 2019-12-05 15:13:11
简化假设:假定基于x86或x64的体系结构,但请指出可能影响基于RISC的体系结构的任何假设,例如Power芯片或Arm芯片。计算精度是首要要求。 易于维护将是下一个要求。计算速度很重要,但比其他要求高。计算需要能够安全地支持操作精确到工厂以及配套值范围达万亿(10 ^ 9)与其他问题的区别:如上所述,以前已经针对其他多种语言提出了此类问题。这个问题与其他问题有所不同,原因有两个。使用以下来源接受的答案:为什么不使用Double或Float代表货币?,让我们重点介绍它们之间的差异。(解决方案1)几乎可以在任何语言下工作的解决方案是改用整数,并计算分。例如,1025为$ 10.25。几种语言还具有内置类型来处理金钱。(解决方案2)除其他外,Java具有BigDecimal类,而C#具有十进制类型。重点强调了两个建议的解决方案第一种解决方案本质上是“定点”方法的一种变体。该解决方案存在一个问题,即建议的范围(跟踪分)不足以进行基于轧机的计算,并且舍入会丢失大量信息。另一种解决方案是使用decimal在C中不可用的本机类。同样,答案不考虑其他选项,例如创建用于处理这些计算的结构或使用任意精度库。这些差异是可以理解的,因为Java没有结构,为什么在语言中有本机支持的情况下为什么还要考虑第三方库。这个问题不同于该问题和其他相关问题,因为C没有相同级别的本机类型支持,并且具有其他语言没有的语言功能。而且我还没有看到其他任何问题可以解决在C语言中可以采用的多种方法。问题:根据我的研究,float由于浮点错误,似乎不适合用于在C程序中表示货币的数据类型。我应该用什么来用C表示金钱,为什么这种方法比其他方法更好?
查看完整描述

3 回答

?
慕后森

TA贡献1802条经验 获得超5个赞

使用整数数据类型(long long,long,int)或BCD(二进制编码的十进制)算术库。您应存储将显示的最小数量的十分之一或百分之一。就是说,如果您使用美元并以美分(百分之一美元)表示,则您的数值应为代表毫或毫的整数(十分之一或百分之一)。额外的重要数字将确保您的兴趣和类似的计算始终如一。

如果使用整数类型,请确保其范围足够大以处理关注的数量。


查看完整回答
反对 回复 2019-12-05
?
四季花海

TA贡献1811条经验 获得超5个赞

最好的货币/货币表示形式是使用诸如doublehas 那样的精度更高的浮点类型FLT_RADIX == 10。这些平台/编译器是罕见的,因为绝大多数系统都有FLT_RADIX == 2。


四种选择:整数,非十进制浮点数,特殊十进制浮点数,用户定义的结构。


整数:常见的解决方案是使用所选货币的最小面额的整数计数。以美分代替美元为例。整数的范围必须合理地宽。喜欢的东西long long,而不是int因为int只能处理大约+/- $ 320.00。这对于涉及加/减/复数的简单会计任务效果很好,但是开始会被除以利息计算中的除法和复杂函数。每月付款方式。有符号整数数学运算没有溢出保护。四舍五入结果时应加倍小心。 q = (a + b/2)/b还不够好。


二进制浮点数:2个常见的陷阱:1)使用float它经常精度不足,并且2)舍入不正确。double对于许多会计限制,使用井解决了问题1。然而,代码仍然经常需要使用四舍五入到所需的最小货币单位以获得令人满意的结果。


// Sample - does not properly meet nuanced corner cases.

double RoundToNearestCents(double dollar) {

  return round(dollar * 100.0)/100.0;

}

一种变化double是使用double最小单位的数量(0.01或0.001)。一个重要的优点是能够通过使用round()本身满足特殊情况的函数来简单地四舍五入。


特别十进制浮点 某些系统提供了一个“小数”类型以外的其他double符合 DECIMAL64或类似的东西。尽管这可以解决上述大多数问题,但是却牺牲了可移植性。


用户定义的结构(如定点)当然可以解决所有问题,只是它很容易出错,并且很容易工作(取而代之)。结果可能会完美运行,但缺乏性能。


结论这是一个很深的主题,每种方法都应该进行更广泛的讨论。普遍的答案是:没有通用的解决方案,因为所有方法都有明显的弱点。因此,这取决于应用程序的细节。


[编辑]

给定OP的其他编辑,建议使用double最小货币单位的编号(例如:$ 0.01-> double money = 1.0;)。每当需要精确值时,请在代码中的各个位置使用round()。


double interest_in_cents = round(

    Monthly_payment(0.07/12 /* percent */, N_payments, principal_in_cents));

我的水晶球说,到2022年,美国将下降0.01美元,最小单位为0.05美元。我将使用能够最好地应对这一转变的方法。


查看完整回答
反对 回复 2019-12-05
?
胡说叔叔

TA贡献1804条经验 获得超8个赞

如果速度是您的首要考虑因素,那么请使用按比例缩放到您需要代表的最小单位的整数类型(例如,磨机,它是0.001美元或0.1美分)。因此,123456代表$123.456。


这种方法的问题是数字可能用完了。一个32位无符号int可以表示10个十进制数字,因此在此方案下您可以表示的最大值为$9,999,999.999。如果您需要处理数十亿美元的价值,那就不好了。


另一种方法是使用结构类型,其中一个整数成员代表整个美元金额,另一个整数成员代表小数美元金额(同样,缩放为您需要代表的最小单位,无论是美分,米尔斯还是其他较小),类似于timeval在一个字段中节省整秒,而在另一字段中节省纳秒的结构:


struct money {

  long whole_dollars; // long long if you have it and you need it

  int frac_dollar; 

};                          

一个int是更比宽足以应付任何缩放理智的人会使用。如果该whole_dollars部分为0,则保留它的签名。


如果您更担心存储任意大的值,那么总是有BCD,它可以表示比任何本机整数或浮点类型更多的数字。


不过,代表制只是成功的一半。您还必须能够对这些类型执行算术运算,并且对货币的运算可能具有非常特定的舍入规则。因此,在决定自己的代表时,您需要考虑这一点。


查看完整回答
反对 回复 2019-12-05
  • 3 回答
  • 0 关注
  • 882 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信