Αποστολέας Θέμα: Ακρίβεια πραγματικών αριθμών  (Αναγνώστηκε 209 φορές)

alkisg

  • Τεχνικός / καθαρίστρια
  • *****
  • Μηνύματα: 5397
    • Ο Διερμηνευτής της ΓΛΩΣΣΑΣ
Ακρίβεια πραγματικών αριθμών
« στις: 07 Απρ 2020, 09:36:19 πμ »
Πάμε στην Python ή σε οποιαδήποτε άλλη γλώσσα και γράφουμε:
print(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 == 1)

Απαντάει "False". Δηλαδή αν προσθέσουμε δέκα φορές το 0.1, δεν μας κάνει 1, αλλά 0.999999999.
Αυτό δημιουργεί προβλήματα σε συγκρίσεις, σε ΓΙΑ που χρησιμοποιούν πραγματικούς αριθμούς οι οποίες εκτελούνται μια φορά λιγότερη ή περισσότερη κλπ.
Ο Διερμηνευτής λύνει αυτό το πρόβλημα περιορίζοντας την ακρίβεια των συγκρίσεων, οπότε θεωρεί ότι 0.999999999 είναι ίσο με 1 και όλα καλά.

Η ερώτηση μου είναι: καλά κάνει ο Διερμηνευτής και κρύβει αυτό το θέμα από τους μαθητές, ή θα προτιμούσαμε να φαίνεται, όπως και στις πραγματικές γλώσσες προγραμματισμού;

dski

  • Δεινόσαυρος
  • *****
  • Μηνύματα: 194
Απ: Ακρίβεια πραγματικών αριθμών
« Απάντηση #1 στις: 07 Απρ 2020, 11:04:12 πμ »
Προσωπική μου γνώμη ότι αυτού του είδους οι λεπτομέρειες καλώς δεν φτάνουν στους μαθητές. Ένας φοιτητής και μελλοντικός επαγγελματίας φυσικά θα πρέπει να γνωρίζει αυτά τα θέματα όμως οι μαθητές, οι οποίο μετά βίας έχουν ακούσει κάποια πράγματα για δυαδικό σύστημα και δυαδικές αναπαραστάσεις στο γυμνάσιο, δεν έχουν το υπόβαθρο να μπουν σε τέτοιες λεπτομέρειες. Επιπλέον οι μαθητές εξετάζονται στο χαρτί οπότε εκεί δεν νομίζω ότι κανείς μπορεί να τους προσάψει λάθος ότι 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 ίσως και να μην κάνει 1 όταν εκτελεστεί στον Η/Υ...

Τέλος, πέρα από όλα αυτά, νομίζω ότι κάτι τέτοιο ξεφεύγει και από τους σκοπούς του μαθήματος. Ναι, συζητάμε ότι ίσως είναι καλό να φύγουμε πλέον από τη Γλώσσα και να πάμε σε μια πραγματική γλώσσα προγραμματισμού όπως η Python αλλά μην ξεχνάμε ότι στόχος είναι να μάθουν οι μαθητές βασικές αρχές ανάλυσης προβλήματος, αλγορίθμων, προγραμματισμού κτλ. Συχνά δυσκολεύονται ακόμα και με απλούστερες βασικές έννοιες, δεν νομίζω ότι θα τους ωφελήσει καλό να μπουν και σε τέτοιες λεπτομέρειες. Θα μπορούσε απλώς αυτό να αναφερθεί σαν, ας πούμε, εγκυκλοπαιδική γνώση, αλλά όχι να αποτελέσει θέμα προς διδασκαλία και κατανόηση από τους μαθητές...

ApoAntonis

  • Βετεράνος
  • ****
  • Μηνύματα: 86
Απ: Ακρίβεια πραγματικών αριθμών
« Απάντηση #2 στις: 07 Απρ 2020, 11:52:46 πμ »
Πάμε στην Python ή σε οποιαδήποτε άλλη γλώσσα και γράφουμε:
print(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 == 1)

Απαντάει "False". Δηλαδή αν προσθέσουμε δέκα φορές το 0.1, δεν μας κάνει 1, αλλά 0.999999999.

δίκοπο...
print 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 == 0.999999999
ούτε και αυτό δίνει True
(με 16 εννιάρια όμως αλλάζει το αποτέλεσμα)

ενώ το
print 1.0/3 + 1.0/3 +1.0/3 == 1
παράγει True





alkisg

  • Τεχνικός / καθαρίστρια
  • *****
  • Μηνύματα: 5397
    • Ο Διερμηνευτής της ΓΛΩΣΣΑΣ
Απ: Ακρίβεια πραγματικών αριθμών
« Απάντηση #3 στις: 07 Απρ 2020, 12:32:04 μμ »
Ναι το 0.999999999 το είπα για συντομία, όχι ως ακριβές αποτέλεσμα. Για μεγαλύτερη ακρίβεια, στη C:
    printf("%0.60lf\n", 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1);
Τυπώνει: 0.999999999999999888977697537484345957636833190917968750000000

Επομένως ο Διερμηνευτής μένει ως έχει, ενώ αν ποτέ το γυρίσουμε σε Python, τότε θα πρέπει ο κάθε καθηγητής να αποφεύγει παραδείγματα που εμπλέκουν οριακές συγκρίσεις πραγματικών αριθμών, όπως είναι οι επαναλήψεις με πραγματικό βήμα, π.χ. ΓΙΑ μ ΑΠΟ 0 ΜΕΧΡΙ 1 ΜΕ_ΒΗΜΑ 0.1.

alkisg

  • Τεχνικός / καθαρίστρια
  • *****
  • Μηνύματα: 5397
    • Ο Διερμηνευτής της ΓΛΩΣΣΑΣ
Απ: Ακρίβεια πραγματικών αριθμών
« Απάντηση #4 στις: 07 Απρ 2020, 02:29:15 μμ »
Υ.Γ. βρήκα μικρότερο παράδειγμα στο https://docs.python.org/3/tutorial/floatingpoint.html
print(0.1 + 0.1 + 0.1 == 0.3)
Βγάζει False.

Ή αντίστοιχα μια ΓΙΑ σε C:
Κώδικας: C
  1. int main(void) {
  2.     double f;
  3.     for (f = 0.1; f <= 0.3; f += 0.1)
  4.         printf("%0.60lf\n", f);
  5. }

Κάνει μόνο 2 επαναλήψεις:
0.100000000000000005551115123125782702118158340454101562500000
0.200000000000000011102230246251565404236316680908203125000000
Ενώ δεν δείχνει την επόμενη, αφού είναι πάνω από 0.3:
0.300000000000000044408920985006261616945266723632812500000000
Ακριβώς 0.3 δεν υπάρχει, οπότε η σταθερά 0.3 ουσιαστικά είναι η:
0.299999999999999988897769753748434595763683319091796875000000).

Και φυσικά αντίστοιχο πρόβλημα δημιουργείται και στις συναρτήσεις τύπου Ακέραιο Μέρος...