Apanepai Δημοσ. 18 Απριλίου 2007 Δημοσ. 18 Απριλίου 2007 Kalispera paidia. Kamia idea gia to pws prolambanoume periptwsi overflow se kaloumeni sunartisi pou upologizei megalo ginomeno??? Euxaristw proairetika
myle Δημοσ. 18 Απριλίου 2007 Δημοσ. 18 Απριλίου 2007 Το γινόμενο δυο αριθμών δεν μπορεί να είναι σε μήκος μεγαλύτερο από το άθροισμα των μηκών των δύο παραγώντων. Άρα αν για το αποτέλεσμα δεσμεύεις μνήμη τόση όση είναι και για τους δύο παράγοντες μαζί είσαι εντάξει.
Apanepai Δημοσ. 18 Απριλίου 2007 Μέλος Δημοσ. 18 Απριλίου 2007 Polu swsta auto pou les kai me boithise arketa sti thewritiki katanoisi. Ti kanoume omws otan oi eisagwgi twn arithmwn ginetai apo ton xristi? Kamia idea gia ton kwdika? Kati brika sxetika me tin LIMITS.H kai INTMAX alla den to polukatalaba.
Legionnaire Δημοσ. 18 Απριλίου 2007 Δημοσ. 18 Απριλίου 2007 Στην limits.h ορίζεται ο τύπος INT_MAX που είναι ο μεγαλύτερος ακέραιος που μπορεί να χωρέσει σε μια μεταβλητή τύπου int. Βέβαια αν μιλάμε για userinput τα πράγματα δεν είναι τόσο εύκολα. Αν ας πούμε διαβάζεις με scanf() π.χ. scanf("%d", &i) οπου i (int) τότε η μεταβλητή i θα πάρει την μεγαλύτερη δυνατή τιμή (αν μιλάμε για 32 bit, +2,147,483,647) άσχετα αν ο χρήστης δώσει ένα πολύ μεγαλύτερο νούμερο. Δηλαδή είτε δώσει +2,147,483,650 είτε +3,999,999,999, η i θα ισούται με την τιμή που ήδη ανέφερα. Παρόμοια αποτέλεσματα θα έχεις αν διαβάζεις string και χρησιμοποιείς την atoi() για να επιστρέψεις int. Βέβαια θα μπορούσες να διαβάζεις unsigned int που χωράει αριθμούς 0...2^32 αντί για 0...2^16-1 που χωράει ο τύπος int. Έτσι αν ας πούμε έχεις unsigned int a και int b μπορείς να έχεις μια δήλωση τύπου > unsigned int a; int b; [...] scanf("%u", &a); if (a > INT_MAX) printf("INT OVERFLOW!\n"); else b = a; [...]
Apanepai Δημοσ. 18 Απριλίου 2007 Μέλος Δημοσ. 18 Απριλίου 2007 Στην limits.h ορίζεται ο τύπος INT_MAX που είναι ο μεγαλύτερος ακέραιος που μπορεί να χωρέσει σε μια μεταβλητή τύπου int. Βέβαια αν μιλάμε για userinput τα πράγματα δεν είναι τόσο εύκολα. Αν ας πούμε διαβάζεις με scanf() π.χ. scanf("%d", &i) οπου i (int) τότε η μεταβλητή i θα πάρει την μεγαλύτερη δυνατή τιμή (αν μιλάμε για 32 bit, +2,147,483,647) άσχετα αν ο χρήστης δώσει ένα πολύ μεγαλύτερο νούμερο. Δηλαδή είτε δώσει +2,147,483,650 είτε +3,999,999,999, η i θα ισούται με την τιμή που ήδη ανέφερα. Παρόμοια αποτέλεσματα θα έχεις αν διαβάζεις string και χρησιμοποιείς την atoi() για να επιστρέψεις int. Βέβαια θα μπορούσες να διαβάζεις unsigned int που χωράει αριθμούς 0...2^32 αντί για 0...2^16-1 που χωράει ο τύπος int. Έτσι αν ας πούμε έχεις unsigned int a και int b μπορείς να έχεις μια δήλωση τύπου > unsigned int a; int b; [...] scanf("%u", &a); if (a > INT_MAX) printf("INT OVERFLOW!\n"); else b = a; [...] Se euxaristw isoun arketa epeksigimatikos kai katatopistikos. Den einai tuxaia to insomnia to num1 forum me tetoia member. Kai pali euxaristw.
Directx Δημοσ. 18 Απριλίου 2007 Δημοσ. 18 Απριλίου 2007 Δες και εδώ http://www.insomnia.gr/vb3/showthread.php?t=172710
myle Δημοσ. 18 Απριλίου 2007 Δημοσ. 18 Απριλίου 2007 Πιστεύω πως η πιο σωστή αντιμετώπιση του προβλήματος είναι να ορίσουμε έναν νέο τύπο δεδομένων που στο ένα μέρος θα αποθηκεύεται το Most Significant Part του αριθμού και στο άλλο το Least. Έτσι δεν θα υπάρχει πρόβλημα με overflows σε καμία περίπτωση. Αυτό βέβαια απαιτεί προγραμματισμό σε low level αλλά μιας και αναφερόμαστε στην C, αυτή μας παρέχει την απαραίτητη ευελιξία που χρειαζόμαστε. Η χρήση unsigned πιστεύω είναι λάθος. Οι unsigned μπορούν απλά να χρησιμοποιήσουν ένα επιπλέον bit για την αναπαράσταση αριθμού αλλά δεν μπορούν να δείξουν αρνητικούς αριθμούς και όπως ξέρουμε αρνητικό αποτέλεσμα δεν είναι λάθος σε ένα γινόμενο. Επίσης, δεν νομίζω ότι σε ενδιαφέρει το εύρος των αριθμών πέρα από τον έλεγχο για να δεις αν μπορεί να αποθηκεύσει αυτό που χρειάζεσαι. Εφ' όσον δεσμεύσης την επιπλέον μνήμη που χρειάζεσαι είναι εξασφαλισμένο ότι δεν θα έχεις πρόβλημα με overflows. Αποδυκνείεται μαθηματικώς. Και η ελάχιστη μνήμη που πρέπει να δεσμεύσεις ώστε σε καμία περίπτωση να μην έχεις πρόβλημα είναι αυτή το άθροισμα των θέσεων μνήμης των δύο παραγόντων. Από εκεί και πέρα είναι θέμα implementation το πόσο αποδοτικά θα γίνει αυτό και τι τύπους δεδομένων θα χρησιμοποιήσεις.
alkisg Δημοσ. 18 Απριλίου 2007 Δημοσ. 18 Απριλίου 2007 Υπάρχει και ο long long (συνήθως 64bit), μπορείς να τον χρησιμοποιήσεις σαν ενδιάμεσο αποτέλεσμα στη συνάρτηση, και έτσι αν το abs(αποτέλεσμα) είναι > 2^32 έχεις overflow. Επίσης για αριθμούς με απεριόριστα ψηφία υπάρχει η βιβλιοθήκη της GNU: http://gmplib.org/
Directx Δημοσ. 19 Απριλίου 2007 Δημοσ. 19 Απριλίου 2007 Πάντως για απλές περιπτώσεις Overflow / Underflow σε integers και εφόσον δεν μας ενδιαφέρει ιδιαίτερα το port του κώδικα σε διαφορετικά λειτουργικά ή επεξεργαστές, προτιμώ την γρήγορη και "καθαρή" λύση ελέγχου των CPU status flags (OF/SF) με την βοήθεια της Assembly (JO,JNS).
poscaman Δημοσ. 19 Απριλίου 2007 Δημοσ. 19 Απριλίου 2007 Πάντως για απλές περιπτώσεις Overflow / Underflow σε integers και εφόσον δεν μας ενδιαφέρει ιδιαίτερα το port του κώδικα σε διαφορετικά λειτουργικά ή επεξεργαστές, προτιμώ την γρήγορη και "καθαρή" λύση ελέγχου των CPU status flags (OF/SF) με την βοήθεια της Assembly (JO,JNS). μηπως μπορεις να δωσεις ενα παραδειγματακι γιατι με μπερδεψες λιγο....
Directx Δημοσ. 19 Απριλίου 2007 Δημοσ. 19 Απριλίου 2007 Ο πλέον αξιόπιστος έλεγχος για σφάλματα υπερχείλισης (overflow) ή υποχείλισης (underflow) όσον αφορά signed και unsigned integers (πχ. int, long κ.α.) στην C είναι ο έλεγχος της αντίστοιχης κατάστασης υπερχείλισης ή υποχείλισης του επεξεργαστή (CPU) με την συντονισμένη χρήση των 80x86 εντολών μηχανής «jo» (Jump if Overflow) και «jns» (Jump if Νοτ Signed) οι οποίες παρουσιάζουν την κατάσταση του επεξεργαστή (CPU Status Flags) ύστερα από την εκτέλεση πράξεων. Η μεν «jo label» μεταφέρει την εκτέλεση του κώδικα μας στο σημείο που υποδεικνύει το label εάν το OF flag (OverFlow flag) του επεξεργαστή είναι ενεργό, δηλαδή 1 (set) ενώ η «jns label» μεταφέρει την εκτέλεση του κώδικα μας στο σημείο που υποδεικνύει το label εάν το SF flag (Sign flag) του επεξεργαστή είναι ανενεργό, δηλαδή 0 (clear). Συγκεκριμένα, οι εντολές «jo» και «jns» πρέπει να χρησιμοποιούνται κάθε φορά που τελείτε μια οποιαδήποτε πράξη και έχετε υπόνοια πως θα μπορούσε να υπάρξει σφάλμα Overflow ή Underflow. Σε περίπτωση λοιπόν που ο 80x86 εντοπίσει Overflow το OF flag και το SF flag γίνονται set (δηλαδή 1), αντίθετα αν ο 80x86 εντοπίσει Underflow το OF flag γίνεται set (δηλαδή 1) αλλά το SF flag γίνεται clear (δηλαδή 0). Συνεπώς, στην πρώτη περίπτωση (Overflow) αρκεί η χρήση της «jo» για να εντοπισθεί το πρόβλημα, στην δεύτερη περίπτωση (Underflow) όμως θα πρέπει αφού επιβεβαιώσετε πως υπάρχει Overflow με την «jo» να κάνετε έναν ακόμα έλεγχο με την «jns» ώστε να διαπιστώσετε εάν το Overflow που υποδεικνύει η «jo» είναι Underflow οπότε σε αυτή την περίπτωση το SF flag θα είναι clear (δηλαδή 0). Ακολουθεί κώδικας γραμμένος σε CodeGear Turbo C++ Explorer που υλοποιεί τον παραπάνω συλλογισμό στην ρουτίνα _CPUMathError (Assembly μορφής 32bit): > //-Overflow/Underflow in C & Assembly----------------------------------------- // Directx. #include <stdio.h> #include <values.h> #ifdef __BORLANDC__ #pragma hdrstop #endif //--------------------------------------------------------------------------- int _CPUMathError(void); #ifdef __BORLANDC__ #pragma argsused #endif int main(int argc, char* argv[]) { // 0 1 2 static char *pszResult[] = { "Normal","Overflow","Underflow" }; // Emulate a signed integer C Overflow unsigned int nOverflow = MAXINT; nOverflow++; printf("_CPUMathError:\"%s\"\nPress any key continue..", pszResult[_CPUMathError()]); fgetc(stdin); // Emulate a signed integer C Underflow nOverflow = -MAXINT; nOverflow-=2; printf("_CPUMathError:\"%s\"\nPress any key continue..", pszResult[_CPUMathError()]); fgetc(stdin); // Quit.. return 0; } //--------------------------------------------------------------------------- int _CPUMathError(void) { /* CPUMathError by Directx (developed under Turbo C++ Explorer) nState: 0 = No error, 1 = Overflow, 2 = Underflow */ int nState; _asm { jo _Overflowed// Is CPU Overflow/Underflow flag set? mov nState,0 // No! jmp _End _Overflowed: // Do we have an Overflow or Underflow? jns _Underflowed // If no sign the we have (?) Underflow mov nState,1 // else Overflow. jmp _End _Underflowed: // We should have underflow mov nState,2 _End: // Complete! } return nState; // Return state.. } Υ.Γ. Disclaimer: Όλα αυτά μέσα από παρατηρήσεις και δοκιμές με τον CPU Disassembler/Debugger της CodeGear Turbo C++
poscaman Δημοσ. 19 Απριλίου 2007 Δημοσ. 19 Απριλίου 2007 οχι παιζουμε!ειδες τι σου ειναι οι ceidάδες?:mrgreen: ευχαριστω πολυ να εισαι καλα.αλλη απορια μιλοντας ομως για assembly δεν εχεις προβλημα μεταφερσιμοτητας του κωδικα?ειτε σε διαφορετικη αρχιτεκτονικη ειτε σε επεξεργαστες διαφορετικης οικογενειας?
Directx Δημοσ. 19 Απριλίου 2007 Δημοσ. 19 Απριλίου 2007 Όπως είπα και προηγουμένως, assembly "εφόσον δεν μας ενδιαφέρει ιδιαίτερα το port του κώδικα σε διαφορετικά λειτουργικά ή επεξεργαστές".
poscaman Δημοσ. 19 Απριλίου 2007 Δημοσ. 19 Απριλίου 2007 Όπως είπα και προηγουμένως, assembly "εφόσον δεν μας ενδιαφέρει ιδιαίτερα το port του κώδικα σε διαφορετικά λειτουργικά ή επεξεργαστές". ουπς!ναι,εχεις δικιο.ευχαριστω για αλλη μια φορα
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.