migf1 Δημοσ. 1 Ιανουαρίου 2014 Δημοσ. 1 Ιανουαρίου 2014 Καλησπέρα, χρόνια πολλά & καλή χρονια! Θα μπορούσε κάποιος που γνωρίζει να επιβεβαιώσει πως η παρακάτω γραμμή κώδικα λειτουργεί as intended όταν θέλουμε να βεβαιώσουμε πως τα off & maxOffset είναι πάντα θετικά και πως το off βρίσκεται μεταξύ 0 (συμπεριλαμβανομένου) και maxOffset? static inline bool _is_valid_offset( float off, const float maxOffset ) { // weird negations in order to avoid float equality comparisons return !(off < 0) && !(maxOffset < 0) && !(off > maxOffset); } Σωστό τον βλέπω και λειτουργεί σωστά σε διάφορες δοκιμές που έχω κάνει, αλλά αναρωτιέμαι μήπως υπάρχει κάποιο corner-case που μου έχει ξεφύγει (και μου σκάσει σε κάποιο μεταγενέστερο στάδιο και ψάχνομαι). Το έχω κάνει έτσι για να αποφύγω περιττή (?) χρήση delta, fabsf() κλπ. Επίσης αν μπορεί να απλοποιηθεί περαιτέρω η έκφραση, ευχαρίστως να την ακούσω και να την υιοθετήσω. Thanks!
παπι Δημοσ. 1 Ιανουαρίου 2014 Δημοσ. 1 Ιανουαρίου 2014 Δεν εχω καταλαβει το τι θες, αλλα τα NOT τι τα θες;
migf1 Δημοσ. 1 Ιανουαρίου 2014 Μέλος Δημοσ. 1 Ιανουαρίου 2014 Επειδή πρόκειται για floats θέλω να αποφύγω απευθείας συγκρίσεις ισότητας. Δηλαδή, το: !(off < 0) είναι σαν το: (off >= 0) αλλά αποφεύγει την ισότητα με το 0. Έπειτα, χωρίς χρήση delta και fabsf() πως αλλιώς θα μπορούσα να ελέγχω για θετικό off αν πάρει π.χ. την τιμή -0.0001?
gon1332 Δημοσ. 1 Ιανουαρίου 2014 Δημοσ. 1 Ιανουαρίου 2014 Καλησπέρα και Καλή χρονιά. Κάνοντας έναν πίνακα αληθείας βρίσκουμε ότι: sign || ret-value | off | maxOffset || A | B | C | =====+=============++=======+=======+=======+ + | + || 1 | 1 | 0{off>max} or 1{off<max} + | - || 1 | 0 |///////| + | 0 || 1 | 1 | 0 | - | + || 0 |///////|///////| - | - || 0 |///////|///////| - | 0 || 0 |///////|///////| 0 | + || 1 | 1 | 1 | 0 | - || 1 | 0 |///////| 0 | 0 || 1 | 1 | 1 | Όπως βλέπουμε οι εγκυρες καταστάσεις, αυτές που θα αποτιμηθούν είναι στις περιπτώσεις όπου off > 0 && maxOffset > 0 && off < maxOffset off = 0 && maxOffset > 0 off = maxOffset = 0 Απλά πρέπει να διευκρινήσεις το 'θετικά'. Θετικά με μηδέν ή χωρίς; Έτσι όπως το έκανες έχεις συμπεριλάβει και το μηδέν στις έγκυρες τιμές των off και maxOffset. Διευκρινίζεις για το off (μπορεί να πάρει μηδενική τιμή), όχι όμως και για το maxOffset. Άρα όλα παίζονται στην τρίτη κουκίδα παραπάνω, όπου το off είναι ή δεν είναι στο πεδίο ορισμού που επιθυμείς.
παπι Δημοσ. 1 Ιανουαρίου 2014 Δημοσ. 1 Ιανουαρίου 2014 _declspec(noinline) bool _is_valid_offset( float off, const float maxOffset ) { // weird negations in order to avoid float equality comparisons return !(off < 0) && !(maxOffset < 0) && !(off > maxOffset); } _declspec(noinline) bool _is_valid_offset_1(float off, float maxOffset) { return off >= 0.f && off <= maxOffset; } int main() { float pi = 3.1415f; int r1 = _is_valid_offset(pi,10.f); int r2 = _is_valid_offset_1(pi,10.f); printf("just compite them %d %d", r1,r2); return 0; } _declspec(noinline) bool _is_valid_offset( float off, const float maxOffset ) { 00E11270 xorps xmm2,xmm2 // weird negations in order to avoid float equality comparisons return !(off < 0) && !(maxOffset < 0) && !(off > maxOffset); 00E11273 comiss xmm2,xmm0 00E11276 ja _is_valid_offset+15h (0E11285h) 00E11278 comiss xmm2,xmm1 00E1127B ja _is_valid_offset+15h (0E11285h) 00E1127D comiss xmm0,xmm1 00E11280 ja _is_valid_offset+15h (0E11285h) 00E11282 mov al,1 } 00E11284 ret // weird negations in order to avoid float equality comparisons return !(off < 0) && !(maxOffset < 0) && !(off > maxOffset); 00E11285 xor al,al } 00E11287 ret --- No source file ------------------------------------------------------------- 00E11288 int 3 00E11289 int 3 00E1128A int 3 00E1128B int 3 00E1128C int 3 00E1128D int 3 00E1128E int 3 00E1128F int 3 --- c:\users\papi\documents\visual studio 2012\projects\cppgtest\cppgtest\main.cpp return off >= 0.f && off <= maxOffset; 00E11290 comiss xmm0,dword ptr ds:[0E1324Ch] 00E11297 jb _is_valid_offset_1+11h (0E112A1h) 00E11299 comiss xmm1,xmm0 00E1129C jb _is_valid_offset_1+11h (0E112A1h) 00E1129E mov al,1 } 00E112A0 ret return off >= 0.f && off <= maxOffset; 00E112A1 xor al,al } 00E112A3 ret
migf1 Δημοσ. 1 Ιανουαρίου 2014 Μέλος Δημοσ. 1 Ιανουαρίου 2014 @gon1332: respect! Θέλω το 0 να λογίζεται στα "θετικά" αλλά τελικά θέλω το off να μην μπορεί να γίνει ίσο με maxOffset. Δηλαδή το off να μπορεί να πάρει τιμές στο εύρος [0, maxOffset)... δλδ από 0 included έως maxOffset excluded... π.χ. (maxOffset - κάποιο_delta). Οπότε ή πρέπει να προσθέσω και 4ο όρο στην έκφραση... static inline bool _is_valid_offset( float off, const float maxOffset ) { // weird negations in order to avoid float equality comparisons return off != maxOffset && !(off < 0) && !(maxOffset < 0) && !(off > maxOffset); } ή να το αφήσω στον caller της συνάρτησης να περνάει αυτό το "κάποιο_delta" στο 2ο όρισμα της συνάρτησης.Π.χ. ... x = read_float(); xmax = read_float(); ... if ( _is_valid_offset(x, max-0.003) ) ... Σωστά τα λεώ; (γιατί έχω κι ένα κεφάλι καζάνι αυτή τη στιγμή).
imitheos Δημοσ. 1 Ιανουαρίου 2014 Δημοσ. 1 Ιανουαρίου 2014 // weird negations in order to avoid float equality comparisons return !(off < 0) && !(maxOffset < 0) && !(off > maxOffset); Δεν εχω καταλαβει το τι θες, αλλα τα NOT τι τα θες; Επειδή πρόκειται για floats θέλω να αποφύγω απευθείας συγκρίσεις ισότητας. Δηλαδή, το: !(off < 0 είναι σαν το: (off >= 0) αλλά αποφεύγει την ισότητα με το 0. Έπειτα, χωρίς χρήση delta και fabsf() πως αλλιώς θα μπορούσα να ελέγχω για θετικό off αν πάρει π.χ. την τιμή -0.0001? Και εγώ έχω την ίδια απορία. Τι κερδίζεις με τον συνδυασμό < και ! σε σχέση με το >= ? Το κλασικό return (off >= 0.0f) && (mO >= 0.0f) && (off < mO) δεν θα είχε το ίδιο αποτέλεσμα με ακριβώς τα ίδια corner-case προβλήματα ?
migf1 Δημοσ. 1 Ιανουαρίου 2014 Μέλος Δημοσ. 1 Ιανουαρίου 2014 @παπι: γράφαμε μαζί, η ανησυχία μου είναι ανακριβή αποτελέσματα σε τυχόν corner-cases που δεν τα έχω προβλέψει. Και εγώ έχω την ίδια απορία. Τι κερδίζεις με τον συνδυασμό < και ! σε σχέση με το >= ? Το κλασικό return (off >= 0.0f) && (mO >= 0.0f) && (off < mO) δεν θα είχε το ίδιο αποτέλεσμα με ακριβώς τα ίδια corner-case προβλήματα ? Μπορεί να λέω βλακείες γιατί πραγματικά είμαι θολωμένος αυτή τη στιγμή (για αυτό και πόσταρα για βοήθεια) αλλά με τα ! δεν αποφεύγω αναξιόπιστο αποτέλεσμα του >= ?
παπι Δημοσ. 1 Ιανουαρίου 2014 Δημοσ. 1 Ιανουαρίου 2014 Μπορεί να λέω βλακείες γιατί πραγματικά είμαι θολωμένος αυτή τη στιγμή (για αυτό και πόσταρα για βοήθεια) αλλά με τα ! δεν αποφεύγω αναξιόπιστο αποτέλεσμα του >= ? Εαν δεις το asm που ποσταρα, θα δεις οτι το NOT το μονο που κανει ειναι να αλλαζει θεση στους registers.
imitheos Δημοσ. 1 Ιανουαρίου 2014 Δημοσ. 1 Ιανουαρίου 2014 @παπι: γράφαμε μαζί, η ανησυχία μου είναι ανακριβή αποτελέσματα σε τυχόν corner-cases που δεν τα έχω προβλέψει. Μπορεί να λέω βλακείες γιατί πραγματικά είμαι θολωμένος αυτή τη στιγμή (για αυτό και πόσταρα για βοήθεια) αλλά με τα ! δεν αποφεύγω αναξιόπιστο αποτέλεσμα του >= ? Εαν δεις το asm που ποσταρα, θα δεις οτι το NOT το μονο που κανει ειναι να αλλαζει θεση στους registers. Όπως λέει ο παπί, με το NOT δεν κερδίζεις κάτι και ίσα ίσα χάνεις γιατί το negation μπορεί να αφήσει να περάσει κάποια χαζομάρα όπως πχ: (τραβηγμένο παράδειγμα το δέχομαι) #include <stdio.h> static inline int _is_1( float off, const float maxOffset ) { return !(off < 0) && !(maxOffset < 0) && !(off > maxOffset); } static inline int _is_2( float off, const float maxOffset ) { return (off > 0.0f) && (off < maxOffset); } int main(void) { float f= 0.0 / 0.0; float m=6; printf("%d\n",_is_1(f,m)); printf("%d\n",_is_2(f,m)); return 0; } Έξοδος: 1 0 Το negation δίνει αποτέλεσμα 1 ακόμα και όταν η σύγκριση αποτυγχάνει λόγω NaN, inf, κτλ.
migf1 Δημοσ. 1 Ιανουαρίου 2014 Μέλος Δημοσ. 1 Ιανουαρίου 2014 Οπότε είναι x-platform safe να τη γράψω με τον καθιερωμένο τρόπο την έκφραση; Δηλαδή με >=, <=, κλπ ?
imitheos Δημοσ. 1 Ιανουαρίου 2014 Δημοσ. 1 Ιανουαρίου 2014 Οπότε είναι x-platform safe να τη γράψω με τον καθιερωμένο τρόπο την έκφραση; Δηλαδή με >=, <=, κλπ ? Αν είναι 100% safe σε όλες τις περιπτώσεις δεν το ξέρω αλλά ο τρόπος που πρότεινε ο παπί είναι σίγουρα καλύτερος από τον τρόπο με το negation. Το off >= 0.0f εγγυάται ότι το offset είναι πραγματικός αριθμός και όχι NaN, κτλ και ότι είναι θετικό ή μηδέν (ο αριθμός 0 αναπαριστάται σωστά όση μικρή ακρίβεια και να έχει ο float οπότε η συγκεκριμένη equality σύγκριση δεν θα πρέπει να έχει ποτέ πρόβλημα) και το off < maxOffset κομμάτι ότι το offset είναι μικρότερο του ορίου (και κατά συνέπεια ότι το μέγιστο όριο είναι θετικό). Edit: Αν το κάνεις έτσι ώστε ο caller να παρέχει κάποιο δέλτα όπως είπες, θα πρέπει να λάβεις μέτρα ώστε αυτό να είναι ικανοποιητικό για το range που έχεις.
migf1 Δημοσ. 1 Ιανουαρίου 2014 Μέλος Δημοσ. 1 Ιανουαρίου 2014 Οκ παιδιά thanks! Το συγκεκριμένο θα το κάνω με το καθιερωμένο (off >= 0 και off < maxOffset) και ο Θεός βοηθός ΥΓ. Κάποια στιγμή μάλλον θα χρειαστώ και implementation αμιγούς ισότητας με fabsf() και delta, αλλά έχω ακόμα καιρό για αυτό.
gon1332 Δημοσ. 1 Ιανουαρίου 2014 Δημοσ. 1 Ιανουαρίου 2014 @gon1332: respect! Θέλω το 0 να λογίζεται στα "θετικά" αλλά τελικά θέλω το off να μην μπορεί να γίνει ίσο με maxOffset. Δηλαδή το off να μπορεί να πάρει τιμές στο εύρος [0, maxOffset)... δλδ από 0 included έως maxOffset excluded... π.χ. (maxOffset - κάποιο_delta). Οπότε ή πρέπει να προσθέσω και 4ο όρο στην έκφραση... static inline bool _is_valid_offset( float off, const float maxOffset ) { // weird negations in order to avoid float equality comparisons return off != maxOffset && !(off < 0) && !(maxOffset < 0) && !(off > maxOffset); } ή να το αφήσω στον caller της συνάρτησης να περνάει αυτό το "κάποιο_delta" στο 2ο όρισμα της συνάρτησης.Π.χ. ... x = read_float(); xmax = read_float(); ... if ( _is_valid_offset(x, max-0.003) ) ... Σωστά τα λεώ; (γιατί έχω κι ένα κεφάλι καζάνι αυτή τη στιγμή). Οι συνθήκες φαίνεται πλέον να δουλεύουν σωστά. Τώρα όσον αφορά το user-level definition of delta, δεν είμαι πολύ σίγουρος γι' αυτό. Πιστεύω ότι με αυτόν τον τρόπο η λειτουργικότητα της συνάρτησης θα εξαρτάται αποκλειστικά από τον χρήστη, κάνοντας πολλές φορές δύσκολο το debugging. Γνώμη μου είναι να υπάρει μία Α προστασία εκ των έσω, διευκολύνοντας το χειριστή του API. Όλα αυτά αν κατάλαβα του τί περίπου θέλεις να κάνεις. Φιλικά.
migf1 Δημοσ. 2 Ιανουαρίου 2014 Μέλος Δημοσ. 2 Ιανουαρίου 2014 @gon: Βασικά το πρόβλημά μου δεν ήταν η λογική των συνθηκών, αλλά τυχόν ανακρίβειες που μπορεί να προκύψουν από ελέγχους ισότητας/ανισότητας μεταξύ float. Τελικά την έκανα με τον απλό τρόπο, αφού παπι & ημίθεος την βρήκαν παπαδιά τη μακαρονάδα που έγραψα... και ο θεός βοηθός τώρα static inline bool _float_is_zero_to_nomax( float f, float max ) { return f >= 0.0f && f < max; }
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα