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

sin#

מחזיר את הסינוס של מספר הנתון ברדיאנים.

sin הוא הסינוס הטריגונומטרי הסטנדרטי: הוא לוקח זווית הנמדדת ברדיאנים ומחזיר את היחס בין הצלע שמול לבין היתר של המשולש ישר־הזווית המתאים. אם EXPR מושמט, sin פועל על $_. התוצאה היא תמיד מספר בנקודה צפה במרווח הסגור [-1, 1].

תקציר#

sin EXPR
sin

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

float בדיוק כפול ב־[-1, 1]. Perl מעביר את הקריאה לשגרת sin(3) של C של הפלטפורמה, כך שהדיוק והעיגול תואמים את ה־libm שלכם. ערכים מיוחדים עוקבים אחר IEEE 754: sin(0) הוא בדיוק 0, sin("inf") ו־sin("nan") שניהם NaN.

רדיאנים, לא מעלות#

הטעות הנפוצה ביותר עם sin היא להזין לו מעלות. סיבוב מלא הוא 2 * π רדיאנים, לא 360. המירו פעם אחת ושמרו את הערך המומר:

use POSIX qw(acos);
my $pi = acos(-1);                  # π to full double precision

sub deg2rad { $_[0] * $pi / 180 }

print sin( deg2rad(30) ), "\n";     # 0.5
print sin( 30 ), "\n";              # -0.988031624092862 - wrong if you meant degrees

Math::Trigext מייצא את deg2rad ו־rad2deg אם אתם מעדיפים לא לכתוב את ההמרה בעצמכם.

דוגמאות#

sin(π/2) הוא מתמטית בדיוק 1, אבל מכיוון ש־π אינו ניתן לייצוג בנקודה צפה בינארית התוצאה המחושבת נופלת קצרה במספר ulpsים:

use POSIX qw(acos);
my $pi = acos(-1);

printf "%.17f\n", sin($pi / 2);     # 1.00000000000000000
printf "%.17f\n", sin($pi);         # 0.00000000000000012 - not exactly 0

התייחסו לכל תוצאה טריגונומטרית ש״צריכה להיות אפס״ כאל קרוב לאפס. השוו עם סבילות, לא עם ==.

המרת מעלות־לרדיאן בשורה, ללא ייבוא מודול. 3.14159 מדויק לשש ספרות - בסדר לשרטוט, לא לאנליזה נומרית:

for my $deg (0, 30, 45, 60, 90) {
    printf "sin(%2d°) = %+.4f\n",
           $deg, sin($deg * 3.14159 / 180);
}
# sin( 0°) = +0.0000
# sin(30°) = +0.5000
# sin(45°) = +0.7071
# sin(60°) = +0.8660
# sin(90°) = +1.0000

לעבודה שדורשת דיוק כפול מלא, החליפו את 3.14159 ב־acos(-1) או atan2(1, 1) * 4.

נגזרת נומרית של sin באמצעות הפרשים סופיים. הנוסחה הסימטרית בשתי נקודות (f(x+h) - f(x-h)) / (2h) אמורה לשחזר את cos(x):

my $x = 1.0;
my $h = 1e-6;
my $deriv = (sin($x + $h) - sin($x - $h)) / (2 * $h);

printf "derivative:  %.10f\n", $deriv;   # 0.5403023059
printf "cos(%.1f):     %.10f\n", $x, cos($x);

בחירת $h היא פשרה: גדול מדי ושגיאת הקטימה דומיננטית, קטן מדי וביטול חיסור הורס את התוצאה. 1e-6 הוא ברירת מחדל סבירה לדיוק כפול.

מעבר על מעגל היחידה והדפסת (cos θ, sin θ) בשמונה זוויות מרוחקות זו מזו במרווחים שווים:

use POSIX qw(acos);
my $pi = acos(-1);

for my $k (0 .. 7) {
    my $theta = $k * $pi / 4;
    printf "%.3f  %+.3f  %+.3f\n",
           $theta, cos($theta), sin($theta);
}

סינוס הפוך (ארקסינוס) דרך הזהות מ־perlfunc:

sub asin { atan2( $_[0], sqrt(1 - $_[0] * $_[0]) ) }

print asin(0.5), "\n";              # 0.523598775598299 (= π/6)

מקרי קצה#

  • ארגומנטים לא־מספריים מומרים בכפייה ל־0. sin("hello") מחזיר 0 מכיוון שהמחרוזת ממוספרת ל־0 קודם. תחת use warnings זה מפיק אזהרה Argument "hello" isn't numeric in sin. בדקו את הקלט עם looks_like_number מ־Scalar::Util אם המקור אינו אמין.

  • ארגומנטים גדולים מאוד מאבדים דיוק. sin מצמצם תחילה את הארגומנט שלו מודולו , ועבור |x| בסדר גודל של 1e16 ה־double הניתן לייצוג הקרוב ביותר נבדל מ־x ביותר מ־π. התוצאה היא עדיין מספר ב־[-1, 1], אבל היא בעצם אקראית. צמצמו את הזווית בעצמכם לפני הקריאה אם אתם צוברים פאזה על פני איטרציות רבות.

  • undef מומר בכפייה ל־0 ומחזיר 0, עם האזהרה הרגילה uninitialized תחת use warnings.

  • מיוחדים של IEEE: sin("inf"), sin("-inf"), ו־sin("nan") כולם מחזירים NaN. השוו עם $result != $result (הערך היחיד שאינו שווה לעצמו) כדי לזהות NaN, או השתמשו ב־POSIX::isnan.

  • ארגומנט ברירת מחדל. sin; ללא ארגומנט קורא את $_. בתוך לולאת while (<>) זה פועל על השורה הנוכחית, מה שכמעט תמיד הוא באג.

  • אין תמיכה במספרים מרוכבים במובנה. לארגומנטים מרוכבים השתמשו ב־Math::Complexext, המעמיס יתר על sin באמצעות העמסת אופרטור:

    use Math::Complex;
    my $z = cplx(1, 2);
    print sin($z), "\n";              # 3.16577851321617+1.9596010414216i
    

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • cos - קוסינוס של זווית ברדיאנים; פונקציית המלווה הנפוצה ביותר לצד sin

  • atan2 - ארקטנגנס דו־ארגומנטי, אבן הבניין הרגילה לטריגונומטריה הפוכה (asin, acos) ב־Perl טהור

  • sqrt - שורש ריבועי; מופיע בזהות הקלאסית של asin asin(x) = atan2(x, sqrt(1 - x*x))

  • Math::Trigext - asin, acos, atan, וריאנטים היפרבוליים, deg2rad/rad2deg, ועוזרי מעגל גדול

  • Math::Complexext - מעמיס יתר על sin (ושאר משפחת הטריגונומטריה) לארגומנטים מרוכבים

  • POSIX - חושף את asin ישירות, בנוסף ל־isnan/isinf לזיהוי התוצאות הלא־סופיות שנדונו לעיל