פונקציות מספריות

sqrt#

החזרת השורש הריבועי הלא־שלילי של EXPR.

sqrt מחשב את השורש הריבועי הראשי - המספר הממשי הלא־שלילי היחיד שריבועו שווה ל־EXPR. עבור כל EXPR >= 0 התוצאה היא >= 0; sqrt אף פעם אינו מחזיר את השורש השלילי. אם EXPR מושמט, נעשה שימוש ב־$_.

החישוב מתבצע בנקודה צפה בדיוק כפול (IEEE 754 binary64), כך שהתוצאה היא float גם כאשר הקלט הוא מספר שלם וגם כאשר התשובה המתמטית עצמה היא מספר שלם.

תקציר#

sqrt EXPR
sqrt
sqrt(EXPR)

מה מקבלים בחזרה#

מספר נקודה צפה: השורש הריבועי הלא־שלילי של EXPR. עבור קלט שלילי התוצאה היא NaN (ואזהרה נפלטת תחת use warnings); ראו מקרי קצה. עבור שורשים בעלי ערך מרוכב טענו את Math::Complexext, שעושה overload ל־sqrt כך ש־sqrt(-1) מחזיר i.

my $r = sqrt 2;                     # 1.4142135623731
my $r = sqrt;                       # sqrt of $_

ארגומנט ברירת המחדל, קדימות, ופירוס#

שלושה פרטי פירוס מעצבים כל קריאת sqrt:

  • ללא ארגומנט נעשה שימוש ב־$_. sqrt ללא ארגומנט וללא סוגריים קורא את משתנה הנושא. שימושי בתוך בלוקי map ו־grep שכבר מקשרים את $_.

  • קדימות אופרטור־אונרי־בעל־שם. sqrt הוא אופרטור אונרי בעל שם, אז הוא נקשר חזק יותר מרוב האופרטורים הבינאריים אך רופף יותר מכפל וחזקה. sqrt 2 + 3 משמעו sqrt(2) + 3, לא sqrt(2 + 3) - סוגריים כשמסופקים.

  • sqrt(...) הוא קריאת פונקציה. כמו עם כל אונרי בעל שם, כתיבת סוגריים פותחים מיד אחרי השם הופכת את השאר לרשימת הארגומנטים: sqrt(4) * 2 הוא 4 (השורש של 4) כפול 2, כלומר 4.

my @roots = map { sqrt } 1, 4, 9;   # (1, 2, 3); $_ is the topic
my $x = sqrt 2 + 3;                 # 4.41421…  - sqrt(2) + 3
my $y = sqrt(2 + 3);                # 2.23606…  - sqrt(5)

דוגמאות#

שורש אי־רציונלי קלאסי. העשרוני המודפס הוא הקירוב הקרוב ביותר ב־binary64, לא הערך המדויק:

printf "%.15f\n", sqrt(2);          # 1.414213562373095

מרחק פיתגורי בין שתי נקודות:

sub distance {
    my ($x1, $y1, $x2, $y2) = @_;
    return sqrt(($x2 - $x1) ** 2 + ($y2 - $y1) ** 2);
}

print distance(0, 0, 3, 4), "\n";   # 5

אפס הוא השורש הריבועי של עצמו, וכך גם אחד:

print sqrt(0), "\n";                # 0
print sqrt(1), "\n";                # 1

ריבועים מושלמים מבצעים round-trip בדיוק עבור מספרים שלמים קטנים, משום שהתוצאה המתמטית ניתנת לייצוג ב־binary64:

print sqrt(16), "\n";               # 4
print sqrt(144), "\n";              # 12
print sqrt(1_000_000), "\n";        # 1000

ריבועים מושלמים גדולים עשויים לא לבצע round-trip בדיוק - התוצאה היא ה־float הקרוב ביותר שניתן לייצוג, שעשוי להיות מעט לא מדויק:

my $n = 9_007_199_254_740_996;      # 2**53 + 4
printf "%.3f\n", sqrt($n) ** 2 - $n; # non-zero in general

השוו לאופרטור החזקה, שהוא הדרך הכללית להעלות לכל חזקה ממשית:

print 2 ** 0.5, "\n";               # same as sqrt(2)
print 27 ** (1/3), "\n";            # cube root of 27 ≈ 3

שימוש ב־Math::Complexext כדי לקבל תוצאה מרוכבת מקלט שלילי:

use Math::Complex;
my $z = sqrt(-1);                   # i
print $z, "\n";                     # "i"
print sqrt(-4), "\n";               # "2i"

מקרי קצה#

  • קלט שלילי ללא Math::Complexext: מחזיר NaN ומפעיל אזהרת Invalid operation תחת use warnings. NaN משווה כלא שווה לעצמו, אז לעולם אל תבדקו עם ==; השתמשו ב־POSIX::isnan או בדקו $x != $x.

    my $r = sqrt(-1);                 # NaN
    print "bad\n" if $r != $r;        # NaN self-compare trick
    
  • קלט שלילי עם Math::Complexext: לאחר ש־Math::Complexext נטען, sqrt עובר overload עבור סקלרים מרוכבים ומחזיר את השורש המרוכב הראשי. קלטים ממשיים עדיין עוברים דרך הפונקציה המובנית.

  • קלט לא־מספרי: נכפה למספר באמצעות הכללים הרגילים - רווח מוביל וקידומת מספרית נצרכים, השאר מושלך. תחת use warnings אזהרת isn't numeric יורה כאשר למחרוזת אין קידומת מספרית כלל. undef נכפה ל־0.

    print sqrt("9abc"), "\n";         # 3, with a warning under warnings
    print sqrt(""), "\n";             # 0, with a warning
    print sqrt(undef), "\n";          # 0, with an uninitialized warning
    
  • אי־דיוק נקודה צפה לריבועים מושלמים: עבור מספרים שלמים גדולים מספיק, השורש המתמטי המדויק עשוי להיות לא ניתן לייצוג. sqrt($n*$n) אינו מובטח להיות שווה ל־$n עבור $n גדול. אם נחוץ שורש ריבועי שלם מדויק, אל תשתמשו ב־sqrt - השתמשו ב־bsqrt של Math::BigIntext או במימוש isqrt ייעודי.

  • ערכי IEEE מיוחדים: sqrt("Inf") הוא Inf; sqrt("NaN") הוא NaN; sqrt(-0.0) הוא -0.0 (אפס שלילי, שמשווה כשווה ל־0). sqrt("-Inf") הוא NaN.

  • גלישה של מספר שלם אינה בעיה: משום שהתוצאה היא תמיד float, sqrt אף פעם אינו גולש עבור כל קלט מספרי סופי.

  • הקשר רשימה אינו רלוונטי: sqrt תמיד מחזיר סקלר יחיד. בהקשר רשימה הסקלר הזה הוא האלמנט היחיד של הרשימה המוחזרת.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • abs - ערך מוחלט; שלבו עם sqrt כשרוצים sqrt(abs($x)) כדי לעקוף קלט שלילי

  • ** - אופרטור חזקה; $x ** 0.5 הוא sqrt, ו־$x ** (1/$n) מכליל לשורשים אחרים

  • hypot - מ־POSIX, מחשב sqrt($x*$x + $y*$y) ללא גלישה ביניים

  • Math::Complexext - עושה overload ל־sqrt וחבריו כך ש־sqrt(-1) מחזיר i במקום NaN

  • Math::BigIntext, Math::BigFloatext - שורשים ריבועיים בדיוק שרירותי באמצעות bsqrt כאשר binary64 אינו מספיק