1

一直在玩 C# 中的复数,我发现了一些有趣的东西。不确定它是错误还是我刚刚错过了什么,但是当我运行以下代码时:

var num = new Complex(0, 1);
var complexPow = Complex.Pow(num, 2);
var numTimesNum = num * num;
Console.WriteLine("Complex.Pow(num, 2) = {0}   num*num = {1}", complexPow.ToString(), numTimesNum.ToString());

我得到以下输出:

Complex.Pow(num, 2) = (-1, 1.22460635382238E-16)   num*num = (-1, 0)

如果没记错的话,复数乘以本身应该只是 -1,没有虚部(或者更确切地说是 0 的虚部)。那么为什么 Complex.Pow(num, 2) 不给 -1 呢?1.22460635382238E-16 来自哪里?

如果重要的话,我正在使用单声道,因为我不在 Windows atm 中。认为它可能是 64 位的,因为我运行的是 64 位操作系统,但我不确定在哪里检查。

保重,克尔。

编辑:

好吧,我解释得不好。我当然是指 i 的平方是 -1,而不是任何复数的平方。感谢您指出。现在有点累,所以我的大脑不太好工作,大声笑。

编辑2:

为了澄清一些事情,我最近一直在阅读一些数学知识,并决定制作一种小型脚本语言来娱乐。好的,“脚本语言”是一个过度声明,它只是评估方程式而已。

4

3 回答 3

7

您会看到浮点不精确。

1.22460635382238E-16实际上是0.00000000000000012...

Complex.Pow()可能是通过De Moivre 公式实现的,使用三角函数来计算任意幂。
因此,它会受到浮点运算和三角函数的不准确的影响。
它显然没有任何积分幂的特殊代码,这可以更简单。

普通的复数乘法只涉及简单的算术运算,所以在整数时不会出现浮点数不准确的情况。

于 2013-06-10T16:41:52.847 回答
7

那么为什么 Complex.Pow(num, 2) 不给 -1 呢?1.22460635382238E-16 来自哪里?

我怀疑这是一个舍入错误,基本上。毕竟,这是一个非常小的数字。我不知道 的细节Complex.Pow,但如果发现它在某处使用了一些三角函数,我一点也不感到惊讶——您很可能会观察到 pi/2 不能完全表示为双精度的事实。

*操作可以通过更简单的定义来避免这种情况 -Complex.Pow 可以在特殊情况下仅使用x * x幂为 2 的地方,但我希望这还没有完成。取而代之的是,使用了一种通用算法,它给出的答案非常接近假设的答案,但可能会导致小错误。

于 2013-06-10T16:42:33.887 回答
3

那么为什么 Complex.Pow(num, 2) 不给 -1 呢?1.22460635382238E-16 来自哪里?

浮点表示的标准问题,以及用于计算的算法Complex.Pow(它不像你想象的那么简单)。请注意,1.22460635382238E-16它非常小,接近机器 epsilon。此外,这里的一个关键事实是它(0, 1)实际上(1, pi / 2)是极坐标,并且pi / 2没有浮点的精确表示。

如果这让您感到不舒服,我建议您阅读每个计算机科学家都应该知道的关于浮点运算的知识。它应该是大学CS课程的必读。

于 2013-06-10T16:43:57.120 回答