سؤال

أشياء غريبة تحدث عند محاولة العثور على الجذر المكعب من عدد.

يعود البرمجية التالية لي غير معروف.في 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)

من الرياضية وسيلة فإنه يجب العمل بما أننا يمكن أن يكون الجذر المكعب من عدد سالب.الأسرى من Visual C++ 2010 الرياضيات.h المكتبة.أي أفكار ؟

هل كانت مفيدة؟

المحلول

pow(x, y) من <cmath> لا يعمل إذا كان x سلبيًا و y غير متطابق.

هذا هو قيود std::pow, ، كما هو موثق في معيار C وعلى cppreference:

معالجة الأخطاء

  • تم الإبلاغ عن الأخطاء كما هو محدد في Math_errhandling
  • إذا كانت القاعدة محدودة وسلبية و EXP محدودة وغير ineger ، فقد يحدث خطأ في المجال وقد يحدث خطأ في النطاق.
  • إذا كانت القاعدة صفرًا و exp كانت صفرًا ، فقد يحدث خطأ في المجال.
  • إذا كانت القاعدة صفرًا و exp سلبي ، فقد يحدث خطأ في المجال أو خطأ في القطب.

هناك طريقتان حول هذا القيد:

  • الجذر المكعب هو نفسه أخذ شيء ما إلى 1/3 ، حتى تتمكن من القيام به std::pow(x, 1/3.).

  • في C ++ 11 ، يمكنك استخدام std::cbrt. قدمت C ++ 11 وظائف الجذر المربعي والجذر ، ولكن لا توجد وظيفة جذر N-Th عامة تتغلب على حدود std::pow.

نصائح أخرى

القوة 1/3 هي حالة خاصة. بشكل عام ، القوى غير المتكاملة للأرقام السلبية معقدة. لن يكون من العملي أن تتحقق أسرى 1/3 كما هو مزدوج ليس بالضبط 1/3!

لا أعرف عن POW Visual C ++ ، لكن صفحة الرجل تقول تحت الأخطاء:

EDOM الحجة x سلبي و y ليست قيمة متكاملة. هذا من شأنه أن يؤدي إلى عدد معقد.

سيتعين عليك استخدام وظيفة جذر مكعب أكثر تخصصًا إذا كنت تريد جذور مكعب من الأرقام السلبية - أو قطع الزوايا واتخاذ القيمة المطلقة ، ثم خذ جذر المكعب ، ثم اضرب الإشارة مرة أخرى.

لاحظ أنه بناءً على السياق ، رقم سالب x إلى 1/3 القوة ليست بالضرورة جذر المكعب السلبي الذي تتوقعه. يمكن أن يكون بنفس السهولة الجذر المعقد ، x^(1/3) * e^(pi*i/3). هذه هي الاتفاقية التي تستخدمها الرياضيات ؛ من المعقول أيضًا أن نقول إنه غير محدد.

بينما (-1)^3 = -1 ، لا يمكنك ببساطة أخذ قوة عقلانية لرقم سالب وتتوقع استجابة حقيقية. هذا لأن هناك حلولًا أخرى لهذا الأسس العقلاني الخيالي في الطبيعة.
http://www.wolframalpha.com/inpt/؟i=x^(1/3)،+x+from+-5+to+0

بالمثل ، قطعة x^x. بالنسبة لـ x = -1/3 ، يجب أن يكون لهذا الحل. ومع ذلك ، تعتبر هذه الوظيفة غير محددة في R لـ X <0.

لذلك ، لا تتوقع من الرياضيات أن تفعل السحر من شأنه أن يجعله غير فعال ، فقط قم بتغيير العلامات بنفسك.

أعتقد أنك يجب أن تأخذ السلبية وتضعه بعد ذلك. يمكنك أن يكون لديك غلاف تفعل هذا من أجلك إذا كنت تريد حقًا.

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> رأس للأسباب التي ذكرها Buddhabrot

pow( x, y ) هو نفسه (أي ما يعادل) exp( y * log( x ) )

إذا كان السجل (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://eadeone.com/bflxys يبدو أنه يؤكد أن C ++ (GCC-4.8.1) يمتد جذر المكعب مع هذه القاعدة cbrt(x)=-cbrt(-x) متى x<0; ؛ لهذا الامتداد يمكنك رؤيته http://mathworld.wolfram.com/cuberoot.html

كنت أبحث عن جذر Cubit ووجدت هذا الموضوع ويحدث لي أن الرمز التالي قد يعمل:

#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;
}

أعتقد أنك يجب ألا تخلط بين الأسعار مع الجذر التام من الرقم. رؤية القديم الجيد ويكيبيديا

نظرًا لأن 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;
}

يستخدم نيوتن رافسون للعثور على جذر مكعب.

في وقت ما ، يتعثر Newton -Raphson ، إذا كان الجذر قريبًا جدًا من 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 خوارزمية أدناه.الفكرة هي أن b و x / b / b أكبر و أصغر من مكعب جذر x.لذا ، فإن متوسط كل من تقع أقرب إلى مكعب جذر x.

الجذر التربيعي و مكعب الجذر (في بايثون)

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_1 و last_b_2 مطلوبة في مكعب الجذر لأن ب ومضات.يمكنك تعديل هذه خوارزميات لحساب الجذر الرابع, الجذر الخامس وهلم جرا.

بفضل مدرس الرياضيات هير برينر في الصف ال11 الذي قال لي هذا خوارزمية sqrt.

الأداء

لقد اختبرت ذلك على اردوينو مع 16mhz بتردد:

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top