0

我想要我的蛋糕并吃掉它。我想在不影响其他计算的准确性的情况下最大程度地美化(四舍五入)数字。我在 C# 中使用双打(也有一些字符串转换操作)。

这就是问题所在。我理解数字表示的固有局限性double(所以请不要解释)。但是,我想以某种方式对数字进行四舍五入,以使最终用户在美学上令人愉悦(我正在制作一个计算器)。问题是 X 有效数字舍入在一种情况下有效,但在另一种情况下无效,而按小数位四舍五入在另一种情况下有效,但不是第一种情况。

观察:

  • 案例 A:Math.Sin(Math.Pi) = 0.000000000000000122460635382238
  • 案例 B:0.000000000000001/3 = 0.000000000000000333333333333333

对于第一种情况,我想按小数位数四舍五入。这会给我我正在寻找的漂亮整洁的零。按 Sig 数字四舍五入意味着我也会保留错误的数字。

但是对于第二种情况,我想按有效数字四舍五入,因为如果仅按小数位四舍五入,我会失去大量的准确性。

有没有一种通用的方法可以同时满足这两种类型的计算?

4

3 回答 3

1

我认为对结果本身这样做是不可行的,精度与它无关。

考虑这个输入:(1+3)/2^3. 您可以通过将结果显示为sin(30)cos(60)1/2以及许多其他解释来“美化”它。选择错误的“美化”可能会误导你的用户,让他们认为他们的功能与sin(x).

如果您的计算器将所有初始输入保留为变量,您可以推迟所有操作,直到您需要结果,然后确保简化结果,直到它符合您的需要。而且你需要考虑使用有理数,e、Pi 和其他无理数可能不太容易处理。

于 2013-07-18T12:59:13.713 回答
1

最好的解决方案是使用任意精度和/或符号算术,尽管这些会导致更复杂的代码和更慢的速度。但是由于性能对于计算器并不重要(如果是按钮计算器,而不是您输入表达式来计算的计算器),您可以毫无问题地使用它们

无论如何,有一个很好的权衡是使用十进制浮点数。您需要限制输入/输出精度,但对内部表示使用更高的精度,以便您可以丢弃非常接近零的值,就像上面的 sin 情况一样。为了获得更好的结果,您可以检测一些边缘情况,例如 45 度倍数的正弦/余弦......并直接返回确切的结果。

编辑:刚刚找到了一个很好的解决方案,但还没有机会尝试。

这是我敢打赌你从来没有想过的事情,并且有充分的理由:浮点数是如何呈现为文本字符串的?这是一个出乎意料的棘手问题,但自 1990 年左右以来,它就被认为已基本解决。

在 Steele 和 White 的“如何准确地打印浮点数”之前,实现printf和类似的渲染函数尽最大努力渲染浮点数,但它们的表现有很大差异。例如,诸如 1.3 之类的数字可能会呈现为 1.29999999,或者如果将一个数字放入写出的反馈循环并将其书面表示读回,则每个连续的结果可能会越来越远离原始结果。

...

2010 年,Florian Loitsch 在 PLDI 上发表了一篇精彩的论文《用整数快速准确地打印浮点数》,这是该领域 20 年来最大的一步:他主要弄清楚了如何使用机器整数进行准确的渲染!为什么我说“大部分”?因为虽然 Loitsch 的“Grisu3”算法非常快,但它放弃了大约 0.5% 的数字,在这种情况下你必须回退到 Dragon4 或衍生品

这里是龙:在你甚至不知道你遇到的问题上取得进展

于 2013-07-27T15:35:13.587 回答
1

最好的解决方案是保留在计算过程中可以获得的每一位,并将显示格式留给最终用户。考虑到计算的性质和结果的使用,用户应该知道有多少有效数字在他们的情况下是有意义的。

对于您在内部使用的浮点格式的一些计算,默认为合理数量的有效数字 - 如果您使用双精度,则约为 12。如果用户更改格式,立即以新格式重新显示。

于 2013-07-18T14:22:46.053 回答