none
Complexの計算で0が変な値になる RRS feed

  • 質問

  • 複素数の計算で

    e^πi=-1

    を計算しようと思い

    MessageBox.Show(Complex.Exp(new Complex(0, Math.PI)).ToString());

    このようにしてみましたが

    結果は

    (-1, 0)

    となるはずが

    (-1, 1.22460635382238E-16)

    と虚部に限りなく0に近い値が表示されてしまいます。

    これは私のやり方に問題があるのか、仕様に問題があるのか

    教えていただけましたら幸いです。

    2017年5月3日 4:17

回答

  • Math.PIなどは無理数ですので、有限の桁数では正しく表現できず、近似値で表現するしかありません。

    なので、計算結果も近似値で表現するしかありません。

    2017年5月3日 4:35
  • e^iθ=Cosθ+iSinθであらわせるのはご存じと思いますが、虚部のMath.Sin(Math.PI)が誤差のせいで0にならないというのが原因ですね。
    例えばSinθの代わりにSQRT(1-(Cosθ)^2)を使うなどの方法も検討してみてはどうでしょう。(符号に注意が必要です)


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2017年5月3日 5:10
  • 補足で、Math.PI

    public const double PI = 3.14159265358979323846;


    と定義されていますし、double自身も16桁程度の精度しかないので、E-16という結果は答えに対して十分近しいかと。

    Math.PIの代わりにMath.Atan(1)*4を使っても精度は上がりませんね。

    # * 4 とは浮動小数点数において指数部+2となるため、精度に影響しない。

    2017年5月3日 14:40

すべての返信

  • Math.PIなどは無理数ですので、有限の桁数では正しく表現できず、近似値で表現するしかありません。

    なので、計算結果も近似値で表現するしかありません。

    2017年5月3日 4:35
  • e^iθ=Cosθ+iSinθであらわせるのはご存じと思いますが、虚部のMath.Sin(Math.PI)が誤差のせいで0にならないというのが原因ですね。
    例えばSinθの代わりにSQRT(1-(Cosθ)^2)を使うなどの方法も検討してみてはどうでしょう。(符号に注意が必要です)


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2017年5月3日 5:10
  • 補足で、Math.PI

    public const double PI = 3.14159265358979323846;


    と定義されていますし、double自身も16桁程度の精度しかないので、E-16という結果は答えに対して十分近しいかと。

    Math.PIの代わりにMath.Atan(1)*4を使っても精度は上がりませんね。

    # * 4 とは浮動小数点数において指数部+2となるため、精度に影響しない。

    2017年5月3日 14:40
  • みなさまご回答いただきありがとうございます。

    Math.PI を使って

    0度、30度、45度、60度、90度等の

    切りのいい数字の時だけは

    別処理にして対応したいと思います。

    ありがとうございます。


    2017年5月4日 4:39
  • 浮動小数点では必ず丸め誤差が生じるということはご存知ですか?

    そんなことは言われなくても百も承知ということでしたら失礼しました。

    でも、もしご存じなければ、「浮動小数点」「丸め誤差」などをキーワードにググるといろいろ参考になる記事が見つかると思いますので、やってみてください。

    例えば下記:

    浮動小数点を利用する際に知っておきたいこと
    https://blogs.msdn.microsoft.com/jpvsblog/2014/10/28/93/


    • 編集済み SurferOnWww 2017年5月4日 22:52 誤記訂正
    2017年5月4日 11:13
  • 「切りのいい数字」を厳密に定義しようとすると、そもそもの「1.22460635382238E-16」をどう解釈するか、と同じ議論に陥ります。sin関数に与える値として30度、45度、60度、90度は、ラジアンでいくつのことでしょうか? sin関数の結果も45度や60度に対してはいくつを期待しますか(いくつと表現したいですか)? 無理数ですが。

    許される丸め誤差が例えば1e-12程度というのであれば、計算結果を画一的に丸める方がずっと単純な解決になると思います。


    • 編集済み 外池 2017年5月4日 11:45
    2017年5月4日 11:44