M2000 Δημοσ. 12 Δεκεμβρίου 2015 Δημοσ. 12 Δεκεμβρίου 2015 Αυτά με τα __future__ δηλαδή πέρα από τις "δεσμευμένες" λέξεις παίζουν και "σινιάλα" ένα σωρό! Γενικά όπως και με το περιβάλλον της Μ2000 δεν γίνεται να μην έχεις κάποια σινιάλα αλλά με μια απλή φόρμα π.χ. Set Future θα είχε καλύτερη εμφάνιση! Αυτό που δείχνεις ως προτέρημα ναι έχει μια αξία με την έννοια ότι φτιάχνεις ένα κανόνα -φόρμουλα- και κάθεται παντού. Αλλά πρακτικά δεν αντιμετωπίσεις το ίδιο θέμα. Θέλω να τσεκάρω την For για παράδειγμα αν του δώσω διάφορες τιμές και βήματα αν θα κάνει τον αριθμό επαναλήψεων που υπολογίζω. Δηλαδή μια For i=.1 to .3 step .1...Next i λογικά δίνει τρία βήματα 0.1, 0.2, 0.3 όμως δεν είναι σίγουρο ότι θα δώσει τρία νούμερα (μπορεί να δώσει 0.1 και 0.2 μόνο) αν ο έλεγχος δεν γίνεται με κάποια στρογγυλοποίηση! Ενώ αν δώσεις μόνο ακέραιους, ή πραγματικούς χωρίς δεκαδικά -με ακέραιες τιμές- δεν έχεις ποτέ πρόβλημα ακρίβειας! Το τσέκαρα στη 2.7.3 >>> [.1*i for i in xrange(1,3)][0.1, 0.2]>>> Δηλαδή δεν δίνει το 0.3 >>> [.1*i for i in xrange(1,4)][0.1, 0.2, 0.30000000000000004]Δεν δίνει 0.3 !
ggeo1 Δημοσ. 12 Δεκεμβρίου 2015 Δημοσ. 12 Δεκεμβρίου 2015 Oφείλεται σε round floating point errors. Μπορείς να κάνεις: for i in range(1,4): ... print(i/10.0) 0.1 0.2 0.3 Ή μπορείς να χρησιμοποιήσεις τη βιβλιοθήκη numpy και την arange.
M2000 Δημοσ. 12 Δεκεμβρίου 2015 Δημοσ. 12 Δεκεμβρίου 2015 Έτσι όμως πας σε ακέραια βήματα και κάνεις αναγωγή σε δεκαδικά με διαίρεση κάθε φορά.. Στις χίλιες επαναλήψεις θα έχεις χίλιες διαιρέσεις συν χίλιες προσθέσεις. Αν το for είχε το βήμα άμεσα τότε θα έκανε μόνο προσθέσεις. Το άλλο δεν το κατάλαβα..(και δεν το ψάχνω... βάλε παράδειγμα αν θες)
ggeo1 Δημοσ. 12 Δεκεμβρίου 2015 Δημοσ. 12 Δεκεμβρίου 2015 Καλύτερα η linspace για float steps. import numpy as np a = np.linspace(0.1,0.3,3) print(a) http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.linspace.html#numpy.linspace Αν δεν το ψάχνεις τότε τί ψάχνεσαι? 2
M2000 Δημοσ. 12 Δεκεμβρίου 2015 Δημοσ. 12 Δεκεμβρίου 2015 Αυτό ήθελα, δηλαδή μια απάντηση με δυο γραμμές και όχι με ένα "Τράβα βρες το" αφού με δυο γραμμές με καλύπτεις! όμως δεν έβαλες το .1 για βήμα αλλά τον αριθμό των βημάτων!
ggeo1 Δημοσ. 12 Δεκεμβρίου 2015 Δημοσ. 12 Δεκεμβρίου 2015 Βάζεις τον αριθμό των σημείων που θέλεις .Πετυχαίνεις αυτό που θέλεις με αυτόν τον τρόπο.
M2000 Δημοσ. 12 Δεκεμβρίου 2015 Δημοσ. 12 Δεκεμβρίου 2015 Ναι αλλά αυτό δεν είναι πρόβλημα πουθενά! Και αρχαία γλώσσα να έχεις μια επανάληψη με ακέραια βήματα γίνεται. Το θέμα είναι πώς γίνεται με μη ακέραια! (ουσιαστικά δεν έχουμε ξεφύγει από την ιδέα της διαίρεσης)
defacer Δημοσ. 12 Δεκεμβρίου 2015 Δημοσ. 12 Δεκεμβρίου 2015 Ναι αλλά αυτό δεν είναι πρόβλημα πουθενά! Και αρχαία γλώσσα να έχεις μια επανάληψη με ακέραια βήματα γίνεται. Το θέμα είναι πώς γίνεται με μη ακέραια! Με μη ακέραια δε γίνεται 100% εγγυημένα και σωστά σε καμία γλώσσα χρησιμοποιώντας primitive types. Για προφανείς λόγους (ΙΕΕΕ 754).
M2000 Δημοσ. 13 Δεκεμβρίου 2015 Δημοσ. 13 Δεκεμβρίου 2015 Υπάρχουν περιορισμοί φυσικά! Αλλά η ιδέα μου είναι να προβλέπεις μια προσαύξηση ή το αντίστροφο ώστε να μην κάνεις το >= (αφού το ίσον έχει θέμα) αλλά μόνο το > (ή αντίστοιχα το < και όχι το <=). Για γραφικά χρειάζεται κανείς να κάνει επαναλήψεις με νούμερα με αριθμητική δεκαδικών, αλλά δεν απαιτεί "τεράστια" ακρίβεια!
M2000 Δημοσ. 13 Δεκεμβρίου 2015 Δημοσ. 13 Δεκεμβρίου 2015 Οκ. Πάντως με τη συζήτηση έτρεξα και μερικά σκριπτάκια Python...και αυτό είναι το ζουμί..να λέμε αλλά και να κάνουμε, να βλέπουμε και να μαθαίνουμε!
V.I.Smirnov Δημοσ. 13 Δεκεμβρίου 2015 Δημοσ. 13 Δεκεμβρίου 2015 (επεξεργασμένο) Το 0.3 δεν έχει ακριβή αναπαράσταση στο δυαδικό σύστημα. Ως floating point, το nibble 0011 επαναλαμβάνεται ατέρμονα. Ο compiler στρογγυλοποιεί το τελευταίο bit προς τα πάνω και στην αναπαράσταση το τελευταίο nibble γίνεται 0100, εξ ου και το μεγαλύτερο αποτέλεσμα του 0.3. Η C/C++ έχει το ίδιο πρόβλημα. Η στρογγυλοποίηση μπορεί να ελεγχθεί μέσω εντολών που ελέγχουν την floating point unit (FPU). Π.χ., αν επιλεγεί στρογυλλοποίηση προς τα κάτω, το αποτέλεσμα θα είναι 0.29999999999999999 διότι το τελευταίο nibble θα μείνει όπως είναι. Διδιακτικό είναι το παρακάτω απόσπασμα: int main() { double temp; bool equal; temp = 0.2*3.0; equal = (temp==0.6); printf("%.16e \t %d \n", temp, equal ); printf("%.16e \t %.16e \t %d \n", 0.2*3.0, 0.6, 0.2*3.0==0.6) ); return 0; } Παραδόξως, τo temp=0.2*3 ΔΕΝ ισούται με 0.6 !!! Το 0.6 στην πραγματικότητα το "βλέπει" ως 0.59999999999999998 και το 0.2*3 δίνει 0.60000000000000009 . Στη .NET υπάρχουν εντολές (Math.Round(...) κλπ) με την οποίες μπορεί να επιλεγεί σε ποιο ψηφίο του αριθμού θα γίνει στρογγυλοποίηση και προς ποιά κατεύθυνση. Π.χ., μπορεί να στρογγυλοποιηθεί το παραπάνω στο π.χ. 4ο δεκαδικό και να δίνει 0.6 . Δυστυχώς αυτό αφορά μόνον μεμονωμένες πράξεις/παραστάσεις. Υπάρχει κάποιος τρόπος να γίνει αυτό καθολικά; δηλ. να ρυθμιστεί ώστε ΟΛΕΣ οι πράξεις να στρογγυλεύουν με τον ίδιο τρόπο; Στην fortran το παραπάνω δίνει σωστό αποτέλεσμα αλλά μόνο εν μέρη : program trial implicit none real(8)::temp temp = 0.2_8*3_8;print *, temp, 0.2_8*3, (0.2_8*3==temp), (0.2_8*3==0.6_8) end program Είτε σε απλή, είτε σε διπλή ακρίβεια, δίνει - temp=0.6 που είναι το σωστό (σε αντίθεση με τη C/C++), - για το 0.2*3 τυπώνει σωστά ότι ισούται με 0.6 (σε αντίθεση με τη C/C++), - το 0.2*3==0.6 το δίνει ψευδές (αντίθετα με ότι τυπώνει, και σε συμφωνία με τη C/C++)... Οσο για τα γραφικά, collision detection κ.α., ποτέ δεν γίνεται υπολογισμός με αριθμητική δεκαδικών. Οι βασικές τεχνικές για τη διατήρηση της ευρωστίας είναι - χρήση ανοχών, - "παχιά" επίπεδα, - "παχιά" σώματα, - κοινός διαμοιρασμός υπολογισμών, - αριθμητική διαστημάτων (interval arithmetic), - ακριβείς και ημιακριβείς υπολογισμοί (αντιμετώπιση των floats ως integers κλπ), - αριθμητική αυξημένης ακρίβειας σε κατηγορήματα (predicates) - Επεξ/σία 13 Δεκεμβρίου 2015 από V.I.Smirnov 3
M2000 Δημοσ. 14 Δεκεμβρίου 2015 Δημοσ. 14 Δεκεμβρίου 2015 Στη Μ2000 παίζει λάθος στο κανονικό =, το == κάνει στρογγυλοποίηση στο 10ο δεκαδικό (αυθαίρετα το έβαλα, αλλά σημασία στον προγραμματισμό έχει το εργαλείο και μετά μαθαίνεις τι κάνει, ότι δηλαδή λέμε και εδώ για την python, ο κάθε κατασκευαστής κάνει ότι θέλει) temp = 0.2*3print temp, (0.2*3==temp), (0.2*3==0.6)print temp, (0.2*3=temp), (0.2*3=0.6) ' To (0.2*3=0.6) βγαίνει λάθος Για τα γραφικά ασφαλώς θα χρησιμοποιηθούν floating point αριθμητικά, έχω γράψει στο κώδικα της Μ2000 περιστροφή Bitmap που με την χρήση γραμμικής παρεμβολής δημιουργεί ενδιάμεσα χρώματα. Έχω και ρουτίνα χωρίς floating point αριθμητικά για να περιστρέφω τα sprites γιατί εκεί έχω pixels διάφανα και το ενδιάμεσο δεν έχει νόημα.. (θέλουμε και γρηγοράδα). Αυτό εδώ το τμήμα υπολογίζει τέσσερις συντελεστές που πολλαπλασιάζουν τέσσερα pixels. Το σφάλμα το παίρνω με αφαίρεση! Δηλαδή μετακινώ το σφάλμα του xf στο xf1. Τα mmx και mmy είναι ακέραια. το sx το υπολογίζω πιο πριν sx = temp_image_x / pws και είναι όλα single. xf = Abs((sx - CSng(mmx))) xf1 = 1! - xf yf = Abs((sy - CSng(mmy))) yf1 = 1! - yf Στην απλή περιστροφή έχουμε όλα τα νούμερα σε long. Τα mmx καιι mmy είναι οι δείκτες για το προς περιστροφή mmx = temp_image_x \ pw ............. bDib1(screen_x, screen_y) = bDib(mmx, mmy) Οι ρουτίνες βρίσκονται στο Pichandler.bas (ο κώδικας δίνεται μαζί) Τα παχιά στρώματα που γράφεις είναι το snap...δηλαδή η γειτνίαση με μια κάνναβο, δηλαδή υπάρχουν τακτικώς οριοθετημένα σημεία και κάθε επιλογή μας θα πάει στο κοντινότερο (αν έχει να κάνει με "εισαγωγή"). Όμως ένας κύκλος ή μια καμπύλη δεν ακολουθεί το snap αλλιώς θα παίρναμε ένα γελοίο σχήμα!
V.I.Smirnov Δημοσ. 14 Δεκεμβρίου 2015 Δημοσ. 14 Δεκεμβρίου 2015 Οι τεχνικές για τη διατήρηση της ευρωστίας είναι αυτές που έγραψα. Δεν είναι κατάλληλες για κάθε περίπτωση αλλά αυτές είναι. Σε ότι αφορά τα "παχιά σώματα", χρησιμοποιούνται σε collision detection. Π.χ. ένας κύκλος αντιμετωπίζεται ως τόρος, μια ευθεία ως "σωλήνας" κλπ, εισάγοντας έτσι εμμέσως ανοχές για τον υπολογισμό. Τα παχιά επίπεδα το ίδιο Οι ταχύτεροι τρόποι είναι η χρήση βελτιστοποιημένων predicates και η ακέραια αριθμητική των floating points, ο δε ευκολότερος είναι η χρήση ανοχών. -
M2000 Δημοσ. 14 Δεκεμβρίου 2015 Δημοσ. 14 Δεκεμβρίου 2015 Το δέχομαι. Πάνω κάτω η υπέρθεση, να κάνεις κάτι που δυσκολεύεται σε ένα χώρο να μπει σε μεγαλύτερο μετράει. Να γιατί ήθελα η For βάσει του βήματος και των αρχικών και τελικών τιμών να μπορεί να καθορίσει μια τελική τιμή ελαφρώς διαφορετική ώστε η τελική τιμή αν είναι δυνατόν να βγει αλλά σε καμία περίπτωση μια μεγαλύτερη από αυτή (μέσα στην επανάληψη). Το έχω πετύχει σπάζοντας το θέμα σε υποπεριπτώσεις! Αλλά ας γυρίσουμε στο θέμα μας. Η ευκολία της Python να δίνει μια συνάρτηση για κάθε τιμή σημαίνει και την ευκολία να δίνει άλλο αποτέλεσμα βάσει επιλογής που δεν φαίνεται πάνω στο κώδικα στο σημείο που εφαρμόζουμε την συνάρτηση. Αυτό σημαίνει ότι είναι απαραίτητο να ακολουθεί κανείς το κώδικα για να γνωρίζει τι τιμή βάζει ή να δεχτεί στο όνομα να βάζει κάποιο αναγνωριστικό ώστε διαβάζοντας τη γραμμή κώδικα που έχει τη συνάρτηση να ξέρει ότι θα πάρει ακέραιο αποτέλεσμα ή όχι.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα