在c#中接受浮点不准确有什么好处?

在过去的 几天里,我脑子里已经遇到了这个问题,我很难说出我的问题。 但是,我想我已经固定了我想知道的东西。

为什么c#通过使用浮点来存储数据来接受不准确? 使用它比其他方法有什么好处?

例如, Math.Pow(Math.Sqrt(2),2)在c#中并不精确。 有些编程语言可以精确计算它(例如,Mathematica)。

我能想到的一个论点是,计算它确实比仅仅应对不准确要慢得多,但Mathematica和Matlab用于计算巨大的科学问题,所以我发现很难相信这些语言真的比c#慢得多。

那么为什么呢?

PS:我很抱歉用这些问题向你发送垃圾邮件,你们都非常乐于助人

为什么c#通过使用浮点来存储数据来接受不准确?

“C#”不接受性能与准确性的权衡; 用户做或不接受。

C#有三种浮点类型 – float,double和decimal – 因为这三种类型满足了现实世界程序员的绝大多数需求。

float和double适用于“科学”计算,其中对三位或四位小数正确的答案总是足够接近,因为这是原始测量所带来的精度。 假设你将10.00除以3得到3.333333333333。 由于原始测量值可能精确到0.01,因此计算结果偏差小于0.0000000000004这一事实无关紧要。 在科学计算中,您不代表已知的准确数量。 如果原始测量值仅精确到小数点后第二位,则小数点后十五位的不精确度无关紧要

这当然不适用于财务计算。 财务计算的操作数通常精确到小数点后两位并表示精确数量 。 十进制适用于“财务”计算,因为十进制运算结果是精确的,前提是所有输入和输出都可以精确地表示为小数(并且它们都在合理的范围内)。 当然,小数仍然存在舍入误差,但精确的运算正是您在进行财务计算时可能想要精确的运算。

使用它比其他方法有什么好处?

您应该说明您想要比较的其他方法。 在计算机上执行计算有很多不同的技术。

例如,Math.Pow(Math.Sqrt(2),2)在c#中并不精确。 有些编程语言可以精确计算它(例如,Mathematica)。

我们在这一点上要清楚; Mathematica没有完全“计算”根2; 该数字是不合理的,因此无法在任何有限的存储量中精确计算。 相反,mathematica所做的是将数字表示为描述数字生成方式的对象。 如果你说“给我两个平方根”,那么Mathematica本质上会分配一个对象,意思是“将平方根运算符应用于精确数字2”。 如果你然后对它进行说明,那么它就有一个特殊目的逻辑,即“如果你对某些东西的平方根进行平方,则给出原始值”。 Mathematica具有代表各种特殊数字的对象,如pi或e,以及关于这些数字的各种操作如何组合在一起的大量规则。

基本上,它是一个象征性的系统; 它操纵数字的方式与人们做铅笔纸数学时的操作方式相同。 大多数计算机程序操纵数字,如计算器:立即执行计算并将其四舍五入。 如果这是不可接受的,那么你应该坚持使用符号系统。

我能想到的一个论点是,计算它确实比仅仅应对不准确要慢得多,但Mathematica和Matlab用于计算巨大的科学问题,所以我发现很难相信这些语言真的比c#慢得多。

虽然它们的速度并不慢,但浮点数的乘法在现代硬件上确实非常快。 这是符号计算引擎非常复杂 。 它编码了所有基础数​​学规则 ,并且有很多规则! C#不是专业级的符号计算引擎,它旨在成为通用编程语言。

一句话:表现。 浮点算法通常在硬件上实现,并且比其他方法快许多个数量级。

你的MATLAB实例更是虚假。 MATLAB使用双精度浮点运算,就像C#一样。

为什么c#通过使用浮点来存储数据来接受不准确?

这样,浮点支持可以映射到硬件支持浮点的方式,也就是说 – 它或多或少是利用硬件浮点运算的唯一方法,这比软件解决方案快得多。 缺点是硬件表示具有有限位数的浮点,这导致不准确(注意,不准确性是明确定义的)。

表示浮点值的其他方式需要软件解决方案,它显着更慢并且需要更多空间。 “任何人”都可以使用c#中提供的内容实现这一点,包括对可用硬件的本机浮点支持对于“任何人”来说都是非常困难的,如果语言/ CLR中尚未支持这种情况。

对于大多数编程问题,不准确性不是问题,并且float (或double )数据类型足够好。 许多年前,没有“浮点值”这样的东西,软件必须存储两个整数这样的值。 性能一个问题(没有提到编程错误 – 和wtf场景 – 来自自定义浮点计算函数)。 因此,设计了一个惯例,并且在计算机配备FPU之后不久。

现在,何时使用FPU进行计算或使用其他数学图书馆/程序(如Mathematica)取决于问题。 例如,在3d环境中计算顶点会优先考虑性能而不是精度。 但会计软件是不同的。 在这方面,两个问题都不同; 一个会计软件不需要每秒数百万次计算复数:)( 编辑 :如果确实如此,一些非常昂贵的硬件也可能是等式的一部分!)

如果你知道你将要做Math.pow(Math.sqrt(2),2)那么你应该重新考虑存储两个值的方式(比如每次重新计算它们)。 这不是编程语言的问题,而是概念问题。

C#和大多数其他语言(除了特定的语言,如Matlab)将浮点数存储为固定大小的字段(6或8字节),这会导致不准确。

一个原因是数字和数字格式是明确的和普遍的。 是的,存在舍入误差,但它们是恒定且可预测的。 尝试为任何算法问题设置通用格式并非易事。

这里有一些mathematica的解释

短版本用于常规的日常浮点数学运算,硬件可以在已知的不准确度下快速完成。 因此,如果您的计算不依赖于更精确,那么快速进行。

如果确实需要精度,那么程序员必须将算法编写为所需的精度。 哪个会慢一些。

我不认为这是c#问题。 c#是一种通用语言,为您提供基本数据类型。 如果你对他们不满意,你总是可以自由创造自己的。

此外,c#不是接受不准确的人。 程序员呢。 对于大量问题,不准确是可以接受的。 如果预期得到确切的结果,则不应使用Float,但这是程序员不是语言设计者的决定。