Αριθμητικές συναρτήσεις

sin#

Επιστρέφει το ημίτονο αριθμού δοθέντος σε ακτίνια.

Η sin είναι το τυπικό τριγωνομετρικό ημίτονο: παίρνει γωνία μετρημένη σε ακτίνια και επιστρέφει τον λόγο της απέναντι πλευράς προς την υποτείνουσα του αντίστοιχου ορθογωνίου τριγώνου. Αν παραλειφθεί το EXPR, η sin λειτουργεί στο $_. Το αποτέλεσμα είναι πάντα αριθμός κινητής υποδιαστολής στο κλειστό διάστημα [-1, 1].

Σύνοψη#

sin EXPR
sin

Τι επιστρέφεται#

Αριθμός κινητής υποδιαστολής διπλής ακρίβειας στο [-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 πρώτα ανάγει το όρισμά της modulo , και για |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 (<>) αυτό λειτουργεί στην τρέχουσα γραμμή, που σχεδόν πάντα είναι bug.

  • Καμία υποστήριξη μιγαδικών αριθμών στην ενσωματωμένη. Για μιγαδικά ορίσματα χρησιμοποιήστε το Math::Complexext, που υπερφορτώνει την sin μέσω υπερφόρτωσης τελεστών:

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

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream 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 για ανίχνευση των μη πεπερασμένων αποτελεσμάτων που συζητούνται παραπάνω