Jam*_*Ide 257 c# floating-point double types decimal
我可以说使用double(或float)代替以下三个优点decimal:
但这些优势似乎只适用于计算密集型操作,例如建模软件中的操作.当然,在需要精确度时,不应使用双精度数,例如财务计算.那么有没有任何实际的理由选择double(或float)而不是decimal"正常"的应用程序?
编辑补充:感谢所有伟大的回应,我向他们学习.
还有一个问题:一些人认为双打可以更精确地代表实数.宣布时,我认为他们通常也会更准确地代表他们.但是,当执行浮点运算时,准确度是否会降低(有时是显着的)是真实的说法吗?
Nol*_*rin 300
我认为你已经很好地总结了这些优势.但是你缺少一点.该decimal类型在表示基数10时(例如用于货币/金融计算的数字)更准确.一般来说,这种 double类型至少会提供很高的精度(如果我错了,有人会纠正我),并且对任意实数来说肯定会提高速度.简单的结论是:在考虑使用哪种时,double除非您需要提供的base 10准确性,否则始终使用decimal.
编辑:
关于操作后浮点数准确性降低的其他问题,这是一个稍微微妙的问题.实际上,在执行每个操作之后,精度(我在这里可互换地使用术语)将稳定地减少.这是由于两个原因:
在所有情况下,如果你想比较理论上应该相等的两个浮点数(但是使用不同的计算得出),你需要允许一定程度的容差(多少变化,但通常非常小) .
有关可以引入精度误差的特定情况的更详细概述,请参阅Wikipedia文章的"准确性"部分.最后,如果您想要在机器级别对浮点数/操作进行认真深入(和数学)的讨论,请尝试阅读经常引用的文章"每个计算机科学家应该知道的关于浮点算术的内容".
Mic*_*ows 57
您似乎可以看到使用浮点类型的好处.我倾向于在所有情况下设计小数,并依靠分析器让我知道十进制操作是否导致瓶颈或减速.在这些情况下,我将"向下转换"为double或float,但仅在内部执行,并通过限制正在执行的数学运算中的有效位数来小心地尝试管理精度损失.
通常,如果您的值是瞬态的(不重用),则可以安全地使用浮点类型.浮点类型的真正问题是以下三种情况.
123456789.1 * .000000000000000987654321)编辑
所述的十进制关键字表示128位的数据类型.与浮点类型相比,十进制类型具有更高的精度和更小的范围,这使其适用于财务和货币计算.
所以澄清我的上述说法:
我倾向于在所有情况下设计小数,并依靠分析器让我知道十进制操作是否导致瓶颈或减速.
我只在小数有利的行业工作过.如果你正在研究phsyics或图形引擎,那么设计浮点类型(float或double)可能更有利.
十进制不是无限精确的(在原始数据类型中不可能表示非整数的无限精度),但它比双精度要精确得多:
编辑2
针对Konrad Rudolph的评论,第1项(上文)绝对是正确的.不精确的聚合确实复杂化.请参阅以下代码以获取示例:
private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;
public static void Main(string[] args)
{
Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
float asSingle = 0f;
double asDouble = 0d;
decimal asDecimal = 0M;
for (int i = 0; i < ONE_MILLION; i++)
{
asSingle += THREE_FIFTHS;
asDouble += THREE_FIFTHS;
asDecimal += (decimal) THREE_FIFTHS;
}
Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
这输出如下:
Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,即使我们从相同的源常量中添加,double的结果也不那么精确(尽管可能会正确地舍入),并且float的精确度要低得多,直到它只减少到只有两位有效数字.
Joe*_*Joe 24
使用十进制作为基数10的值,例如财务计算,正如其他人所建议的那样.
但对于任意计算值,double通常更准确.
例如,如果要计算投资组合中每一行的权重,请使用double,因为结果将更接近100%.
在以下示例中,doubleResult比decimalResult更接近1:
// Add one third + one third + one third with decimal
decimal decimalValue = 1M / 3M;
decimal decimalResult = decimalValue + decimalValue + decimalValue;
// Add one third + one third + one third with double
double doubleValue = 1D / 3D;
double doubleResult = doubleValue + doubleValue + doubleValue;
Run Code Online (Sandbox Code Playgroud)
再次以组合为例:
投资组合中每条线的市场价值是货币价值,可能最好用十进制表示.
投资组合中每条线的权重(=市场价值/ SUM(市场价值))通常更好地表示为双倍.
当你不需要精确度时,使用double或float,例如,在我写的平台游戏中,我使用浮动来存储玩家的速度.显然我在这里不需要超精确,因为我最终会绕过Int来绘制屏幕.
在某些会计中,考虑使用整数类型替代或结合使用的可能性。例如,假设您所遵循的规则要求每个计算结果至少保留 6 位小数,并且最终结果将四舍五入到最接近的便士。
100 美元的 1/6 的计算结果为 16.66666666666666...,因此工作表中的值将为 16.666667 美元。double 和decimal 都应将结果精确到小数点后6 位。但是,我们可以通过将结果作为整数 16666667 向前推进来避免任何累积误差。后续的每次计算都可以使用相同的精度进行,并类似地向前推进。继续这个例子,我计算了该金额的德克萨斯州销售税 (16666667 * .0825 = 1375000)。将两者相加(这是一个简短的工作表)1666667 + 1375000 = 18041667。将小数点向后移,得到 18.041667,即 18.04 美元。
虽然这个简短的示例不会使用双精度或小数产生累积误差,但很容易说明简单计算双精度或小数并结转会累积显着误差的情况。如果您所操作的规则要求小数位数有限,则将每个值存储为整数,方法是乘以 10^(所需的小数位数),然后除以 10^(所需的小数位数)以获得实际值值将避免任何累积误差。
在不存在小数便士的情况下(例如自动售货机),根本没有理由使用非整数类型。只需将其视为数便士,而不是美元。我见过代码中每次计算只涉及整便士,但使用 double 会导致错误!仅整数数学解决了这个问题。所以我非常规的答案是,如果可能的话,放弃双精度和十进制。
| 归档时间: |
|
| 查看次数: |
51708 次 |
| 最近记录: |