将窄类型转换为更宽泛的类型以节省内存并保持高精度计算是一个糟糕的想法?

时间:2009-05-28 16:29:56

标签: c# performance memory casting decimal

我正在处理财务数据,所以它有很多,需要相对较高的精度(64位浮点或更宽)。

围绕我的工作场所的标准做法似乎是将其全部表示为c#decimal类型,这是一个128位宽的浮点,专门用于支持四舍五入的free base10操作。

由于64bit的宽度足以保持代表性的精度,所以将数据转换为更广泛的类型进行所有计算(mult,div,add等)然后回到64位坐在内存(这是哪里)是荒谬的它的时间花费最多吗?

供参考:内存绝对是限制资源。

10 个答案:

答案 0 :(得分:16)

使用十进制(128位)而不是双(64位)和浮点(32位)通常与大小无关。这与基地有关。虽然double和float是浮点二进制点类型,但十进制是一个浮点十进制点类型 - 它的特征是它可以表示像f一样的数字,其中float / double可以'吨。

没有概念上的理由说明为什么我们不能没有64位十进制类型,并且在许多情况下确实已经足够了 - 但是直到这样的类型出现或者你自己编写它, please < / em>不要使用“较短”(和二进制浮点)类型的float / double进行财务计算。如果你这样做,那你就是在寻找麻烦。

如果你建议编写一个可以转换为十进制数并且仍然是十进制数的存储类型,即使没有能够进行任何计算,这听起来也是一个好主意。如果您曾被要求转换一个您无法准确表示的十进制值,那么当您考虑要做什么时,您需要非常小心。老实说,我有兴趣看到这样的类型。嗯...

(正如其他答案所表明的那样,我确实确定这是在做这个之前占用内存的数字。但如果你不需要来做,那就是在推测性地引入额外的复杂性方面没什么意义。)

答案 1 :(得分:5)

64位浮点无法保持财务数据的精确度。它不是空间问题,而是数据类型使用的数字系统的问题; double使用base-2,decimal是base-10,base-2不能表示精确的10进制小数,即使它有1000位精度。

不相信我?运行这个:

double d = 0.0;
for (int i = 0; i < 100; i++)
    d += 0.1;
Console.WriteLine(d);

> 9.99999999999998

如果需要基数为10的计算,则需要十进制类型。

(编辑:该死的,再次被Jon Skeet殴打......)

如果十进制类型确实是瓶颈,你可以使用很多便士(或1/8美元或任何你的单位)而不是十进制美元。

答案 2 :(得分:3)

您应该使用分析器来查看哪些对象占用了大量内存。如果你的小数对象是罪魁祸首,那么我会说是的,追求它们。否则你只是在猜测。 Profiler会告诉你肯定的。

答案 3 :(得分:3)

将数字存储为64位,将它们转换为十进制类型进行计算,并将结果转换回64位,如果您不介意性能损失,这是完全合理的。

我工作时需要这种精确度,所以这正是我们在这里所做的。我们通过执行转换来获得两个数量级的速度,但我们永远不必担心浮点运算中的大错误。如果没有强制转换,计算可能会非常不准确,具体取决于数字的范围和正在执行的计算类型。

有关浮点运算的更多信息,以及为什么错误会蔓延到您的计算中,请参阅http://docs.sun.com/source/806-3568/ncg_goldberg.html上的“每个计算机科学家应该知道的关于浮点运算的内容”

答案 4 :(得分:2)

如果64位浮点真正足以表示您想要的精度,那么这似乎是完全理智的。正如您所说,额外精度十进制通常纯粹用于最大限度地减少多个操作中的累积错误。

答案 5 :(得分:2)

正如大多数其他帖子已经指出的那样,在128位十进制和64位浮点表示之间进行转换并不是一种始终保持准确性的转换。

但是,如果您正在处理金融股的价格,您可以考虑将它们表示为整数(便士的数量)而不是十进制值(分数美元的数量)。以便士执行所有财务计算,然后仅在请求时将它们作为小数显示给外部世界。

另一种方法可能是提高系统的算法效率,而不是“压缩”存储类型。你真的一次需要内存中的所有数据吗?你能以某种方式虚拟化吗?

如果没有,考虑到您管理的数据量,您可能希望以减少冗余的方式组织数据。例如,并非每个股票都有历史价格回溯(有些公司的回溯时间不够远)。因此,按日(或年)的形式将您的数据组织为股票价格字典,而不是作为每种股票的表格结构。根据您的数据可用方式以及您打算如何使用它进行计算,可能还有其他选择。

答案 6 :(得分:0)

你需要进行数值分析,看看练习(保持128位)是荒谬的,还是只是懒惰的,或者是非常必要的。

答案 7 :(得分:0)

“只是添加更多记忆”是一个可接受的答案吗?

正确编码和测试在这些表示之间移动值的建议方法涉及多少成本。比较这个成本与将更多内存铲入机器,应用程序作为64位进程运行。

答案 8 :(得分:0)

从MSDN十进制:浮点类型和十进制类型之间没有隐式转换;因此,必须使用强制转换来转换这两种类型。

在您使用的情况下,看起来需要进行演员表演。

话虽这么说,了解这里的大多数其他人在浮点代表货币问题方面的意义非常重要。

您可以考虑创建/查找可用于系统的64位BCD(二进制编码十进制)实现。

答案 9 :(得分:0)

相同的双精度转换为小数,然后转换为byte [],然后压缩占用的空间减少了c.2倍(我刚用几个压缩库测试了这个:Blosc默认情况下,lz4,zlib有或没有shuffle,带有随机小数是最好的。

一种选择是将压缩小数存储在内存或磁盘上,因为CPU现在正在挨饿。请在此处查看多个演示文稿:http://blosc.org/docs/