Κατηγορίες

Αρχείο

Javascript Math functions & closures

Πρόσφατα , δουλεύοντας σε ένα έργο το οποίο απαιτούσε αρκετά μαθηματικά σε client side κώδικα ήρθα αντιμέτωπος με ένα παλιό πρόβλημα που παρουσιάζουν οι υλοποιήσεις αρκετών μαθηματικών συναρτήσεων στην javascript. Συναρτήσεις όπως οι

Math.round, Math.ceil και Math.floor

είναι ιδιαίτερα χρήσιμες , ωστόσο έχουν το μειονέκτημα ότι δεν επιτρέπουν τον προσδιορισμό του επιπέδου ακρίβειας. Για παράδειγμα η συνάρτηση Math.round στρογγυλοποιεί πάντα τον αριθμό εισόδου στον πλησιέστερο ακέραιο. Συχνά όμως η στρογγυλοποίηση στο ακέραιο μέρος δεν είναι αρκετή. Σε πολλές περιπτώσεις απαιτείται η στρογγυλοποίηση αριθμών κινητής υποδιαστολής (δηλαδή πραγματικών αριθμών) σε προσέγγιση με δεδομένο αριθμό δεκαδικών ψηφίων.Γενικά , για την  παράκαμψη των περιορισμών αυτών χρησιμοποιούμε μια τεχνική που επιτρέπει την στρογγυλοποίηση σε Χ δεκαδικά ψηφία  , υψώνοντας και διαιρόντας με την κατάλληλη δύναμη του 10. Για παράδειγμα :

Math.round(num);      // round num to an integer
Math.round(10*num)/10;     // round num to tenths
Math.round(100*num)/100;   // round num to hundredths
Math.round(1000*num)/1000; // round num to thousandths

Μια πιο γενική λύση είναι να χρησιμοποιήσουμε  τον τύπο : 

Math.round(num*Math.pow(X,10)) / Math.pow(X,10)

 ,όπου X ο αριθμός δεκαδικών ψηφίων στον οποίο θέλουμε να στρογγυλοποιήσουμε.  Το πρόβλημα με την λύση αυτή είναι ότι επαναλαμβάνεται σε μεγάλο βαθμό το ίδιο μοτίβο , μέσα στον κώδικα οπότε η προφανής λύση θα ήταν να ενσωματώσουμε τον παραπάνω τύπο σε μία συνάρτηση την οποία θα καλούμε αντί της Math.round. Μια ακόμα καλύτερη λύση όμως , είναι να χρησιμοποιήσουμε closures , και να κάνουμε overwrite την Math.round. Η λύση αυτή είναι πιο καλή  γιατί μας επιτρέπει να ενσωματώσουμε την επιπλέον λειτουργικότητα στις υπάρχουσες συναρτήσεις της Javascript , με τις οποίες έχουμε συνηθίσει να δουλεύουμε. Για παράδειγμα μπορούμε να κάνουμε overwrite την Math.round με τον παρακάτω κώδικα [1] :

1
2
3
4
5
6
7
8
Math.round = (function() {
var oldRound = Math.round;
return function(number, precision) {
precision = Math.abs(parseInt(precision)) || 0;
var coefficient = Math.pow(10, precision);
return oldRound(number*coefficient)/coefficient;
};
})();

[1] Παρατηρείστε ότι πρώτη εντολή μέσα στο σώμα της εξωτερικής συνάρτησης , κρατάει ένα αντίγραφο της αρχικής Math.round έτσι ώστε να μπορεί να χρησιμοποιηθεί στην συνέχεια από την εσωτερική συνάρτηση.

Με τον τρόπο αυτό  και ο υπάρχον κώδικας εξακολουθεί να εκτελείται κανονικά χωρίς να απαιτείται κάποια αλλαγή , ενώ παράλληλα μπορούμε να γράψουμε εντολές της μορφής Math.round(num,2) για να στρογγυλοποιήσουμε σε ακρίβεια συγκεκριμένων δεκαδικών ψηφίων.  Η τεχνική αυτή μπορεί να χρησιμοποιηθεί και για τις υπόλοιπες μαθηματικές συναρτήσεις που παρουσιάζουν το ίδιο πρόβλημα , επεκτείνοντας έτσι την λειτουργικότητα της αγαπημένης μας client side scripting γλώσσας.

Ολοκληρώνοντας να πω ότι οι closures είναι χαρακτηριστικό της ECMA τυποποίησης και υποστηρίζεται από όλους τους σύγχρονους browsers.

Leave a Reply

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>