質問

数字のキューブルートを見つけようとすると奇妙なことが起こります。

次のコードは私を未定義に返します。 CMD:-1。#ind

cout<<pow(( double )(20.0*(-3.2) + 30.0),( double )1/3)

これは完全に正常に機能しますが。 CMD:4.93242414866094

cout<<pow(( double )(20.0*4.5 + 30.0),( double )1/3)

数学的な方法から、負の数からキューブルートを持つことができるため、機能する必要があります。 PowはVisual C ++ 2010 Math.hライブラリからのものです。何か案は?

役に立ちましたか?

解決

pow(x, y) から <cmath> xが負でyが非統合である場合、機能しません。

これはの制限です std::pow, 、C標準およびオンで文書化されています cppreference:

エラー処理

  • エラーは、math_errhandlingで指定されているように報告されます
  • ベースが有限で負で、EXPが有限で非整数である場合、ドメインエラーが発生し、範囲エラーが発生する可能性があります。
  • ベースがゼロで、EXPがゼロの場合、ドメインエラーが発生する可能性があります。
  • ベースがゼロで、EXPが負の場合、ドメインエラーまたはポールエラーが発生する可能性があります。

この制限にはいくつかの方法があります。

  • キューブルートは1/3のパワーに何かを取ることと同じなので、できます std::pow(x, 1/3.).

  • C ++ 11では、使用できます std::cbrt. 。 C ++ 11は、方形ルートとキューブルートの両方の関数を導入しましたが、の制限を克服する一般的なn番目のルート関数はありません std::pow.

他のヒント

パワー 1/3 特別なケースです。一般に、負の数の非統合力は複雑です。 POWが整数の根のような特別なケースをチェックすることは実用的ではありません。 1/3 ダブルは正確に1/3ではありません!

私は視覚的なC ++ Powについては知りませんが、私の男のページはエラーの下で言っています:

EDOM 議論 x ネガティブです y 不可欠な値ではありません。これにより、複雑な数が生じます。

マイナス数のキューブの根が必要な場合は、より専門的なキューブルート関数を使用するか、コーナーを切り取って絶対値を取得し、キューブルートを取り、サインを再び掛けます。

コンテキストに応じて、負の数に注意してください x1/3 パワーは必ずしもあなたが期待しているネガティブキューブルートではありません。それは同じくらい簡単に最初の複雑なルートになる可能性があります、 x^(1/3) * e^(pi*i/3). 。これは、Mathematicaが使用するコンベンションです。また、それが未定義だと言うことも合理的です。

一方、(-1)^3 = -1は、単に負の数の合理的な力を持ち、実際の応答を期待することはできません。これは、本質的に想像上のこの合理的な指数に他の解決策があるためです。
http://www.wolframalpha.com/input/?i=x^(1/3),+x+ from from from-from-to+0

同様に、x^xをプロットします。 x = -1/3の場合、これには解決策が必要です。ただし、この関数はx <0に対してRで未定義であると見なされます。

したがって、Math.hがそれを非効率的にする魔法をすることを期待しないでください。自分で兆候を変えるだけです。

ネガティブを取り出して、その後それを入れなければならないと思います。あなたが本当にしたいなら、あなたはラッパーにあなたのためにこれをさせることができます。

function yourPow(double x, double y)
{
    if (x < 0)
        return -1.0 * pow(-1.0*x, y);
    else
        return pow(x, y);
}

キャストしないでください double 使用して (double), 、代わりに二重数値定数を使用します。

double thingToCubeRoot = -20.*3.2+30;
cout<< thingToCubeRoot/fabs(thingToCubeRoot) * pow( fabs(thingToCubeRoot), 1./3. );

トリックをする必要があります!

また、含めないでください <math.h> C ++プロジェクトでは使用します <cmath> 代わりは。

または、使用してください pow から <complex> 仏教が述べた理由のためにヘッダー

pow( x, y ) (つまり、同等)と同じです exp( y * log( x ) )

log(x)が無効である場合、pow(x、y)もそうです。

同様に、数学的には0である必要がありますが、何のパワーに対して0を実行することはできません。

C ++ 11には cbrt 関数(たとえば、を参照してください http://en.cppreference.com/w/cpp/numeric/math/cbrt)だから、あなたは次のようなものを書くことができます

#include <iostream>
#include <cmath>

int main(int argc, char* argv[])
{
   const double arg = 20.0*(-3.2) + 30.0;
   std::cout << cbrt(arg) << "\n";
   std::cout << cbrt(-arg) << "\n";
   return 0;
}

私はC ++標準にアクセスできないので、否定的な引数がどのように処理されるかわかりません... IDEONEのテスト http://ideone.com/bflxys C ++(GCC-4.8.1)がこのルールでキューブルートを拡張することを確認しているようです cbrt(x)=-cbrt(-x) いつ x<0;この拡張機能については、表示できます http://mathworld.wolfram.com/cuberoot.html

私はキュービットルートを探していましたが、このスレッドを見つけましたが、次のコードが機能する可能性があることがわかります。

#include <cmath>
using namespace std;

function double nth-root(double x, double n){
    if (!(n%2) || x<0){
        throw FAILEXCEPTION(); // even root from negative is fail
    }

    bool sign = (x >= 0);

    x = exp(log(abs(x))/n);

    return sign ? x : -x;
}

指数を数字のnth-rootと混同してはならないと思います。古き良きを見てください ウィキペディア

1/3は整数と見なされるため、常に0を返します... 1.0/3.0で試してみてください...それは私が思うが実装しようとするものです...そして1.0と3.0を含む変数を宣言することを忘れないでくださいダブルとして...

これが私がノックアップした小さな機能です。

#define uniform() (rand()/(1.0 + RAND_MAX))

double CBRT(double Z)
{
    double guess = Z;
    double x, dx;
    int loopbreaker;

retry:
    x = guess * guess * guess;
    loopbreaker = 0;
    while (fabs(x - Z) > FLT_EPSILON)
    {
        dx = 3 * guess*guess;
        loopbreaker++;
        if (fabs(dx) < DBL_EPSILON || loopbreaker > 53)
        {
            guess += uniform() * 2 - 1.0;
            goto retry;
        }
        guess -= (x - Z) / dx;
        x = guess*guess*guess;
    }

    return guess;
}

ニュートンラフソンを使用してキューブルートを見つけます。

ニュートン - ラフソンが立ち往生します。ルートが0に非常に近い場合、微分が大きくなり、振動することがあります。それで、私はそれが起こった場合にそれを再起動するように固定し、強制しました。より精度が必要な場合は、FLT_EPSILONSを変更できます。

数学ライブラリがない場合は、この方法を使用して立方体のルートを計算できます。

立方根

double curt(double x) {
  if (x == 0) {
    // would otherwise return something like 4.257959840008151e-109
    return 0;
  }
  double b = 1; // use any value except 0
  double last_b_1 = 0;
  double last_b_2 = 0;
  while (last_b_1 != b && last_b_2 != b) {
    last_b_1 = b;
    // use (2 * b + x / b / b) / 3 for small numbers, as suggested by  willywonka_dailyblah
    b = (b + x / b / b) / 2;
    last_b_2 = b;
    // use (2 * b + x / b / b) / 3 for small numbers, as suggested by  willywonka_dailyblah
    b = (b + x / b / b) / 2;
  }
  return b;
}

それはから派生しています sqrt 以下のアルゴリズム。アイデアはそれです bx / b / b の立方体から大きくて小さく x. 。したがって、両方の平均はの立方体に近いものです x.

平方根と立方体(Python)

def sqrt_2(a):
    if a == 0:
        return 0
    b = 1
    last_b = 0
    while last_b != b:
        last_b = b
        b = (b + a / b) / 2
    return b

def curt_2(a):
    if a == 0:
        return 0
    b = a
    last_b_1 = 0;
    last_b_2 = 0;
    while (last_b_1 != b and last_b_2 != b):
        last_b_1 = b;
        b = (b + a / b / b) / 2;
        last_b_2 = b;
        b = (b + a / b / b) / 2;
    return b

平方根とは対照的に、 last_b_1last_b_2 Bはフリッカーであるため、立方体で必要です。これらのアルゴリズムを変更して、4番目のルート、5番目のルートなどを計算できます。

11年生の私の数学の先生であるHerr Brennerに感謝します。 sqrt.

パフォーマンス

16MHzのクロック周波数のArduinoでテストしました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top