Μαθηματικές συναρτήσεις, πέντε παραδείγματα

Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr

Η βιβλιοθήκη μαθηματικών

Το παρακάτω απόσπασμα είναι η τεκμηρίωση της βιβλιοθήκης της Java για τις διαθέσιμες μαθηματικές σταθερές και συναρτήσεις. Όλες χρησιμοποιούνται με το πρόθεμα "Math.". Παράδειγμα:
        double x = Math.cos(Math.PI / 2.);

Field Summary
static double E
          The double value that is closer than any other to e, the base of the natural logarithms.
static double PI
          The double value that is closer than any other to pi, the ratio of the circumference of a circle to its diameter.
 
Method Summary
static double abs(double a)
          Returns the absolute value of a double value.
static float abs(float a)
          Returns the absolute value of a float value.
static int abs(int a)
          Returns the absolute value of an int value.
static long abs(long a)
          Returns the absolute value of a long value.
static double acos(double a)
          Returns the arc cosine of an angle, in the range of 0.0 through pi.
static double asin(double a)
          Returns the arc sine of an angle, in the range of -pi/2 through pi/2.
static double atan(double a)
          Returns the arc tangent of an angle, in the range of -pi/2 through pi/2.
static double atan2(double a, double b)
          Converts rectangular coordinates (ba) to polar (r, theta).
static double ceil(double a)
          Returns the smallest (closest to negative infinity) double value that is not less than the argument and is equal to a mathematical integer.
static double cos(double a)
          Returns the trigonometric cosine of an angle.
static double exp(double a)
          Returns the exponential number e (i.e., 2.718...) raised to the power of a double value.
static double floor(double a)
          Returns the largest (closest to positive infinity) double value that is not greater than the argument and is equal to a mathematical integer.
static double IEEEremainder(double f1, double f2)
          Computes the remainder operation on two arguments as prescribed by the IEEE 754 standard.
static double log(double a)
          Returns the natural logarithm (base e) of a double value.
static double max(double a, double b)
          Returns the greater of two double values.
static float max(float a, float b)
          Returns the greater of two float values.
static int max(int a, int b)
          Returns the greater of two int values.
static long max(long a, long b)
          Returns the greater of two long values.
static double min(double a, double b)
          Returns the smaller of two double values.
static float min(float a, float b)
          Returns the smaller of two float values.
static int min(int a, int b)
          Returns the smaller of two int values.
static long min(long a, long b)
          Returns the smaller of two long values.
static double pow(double a, double b)
          Returns of value of the first argument raised to the power of the second argument.
static double random()
          Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.
static double rint(double a)
          Returns the double value that is closest in value to a and is equal to a mathematical integer.
static long round(double a)
          Returns the closest long to the argument.
static int round(float a)
          Returns the closest int to the argument.
static double sin(double a)
          Returns the trigonometric sine of an angle.
static double sqrt(double a)
          Returns the correctly rounded positive square root of a double value.
static double tan(double a)
          Returns the trigonometric tangent of an angle.
static double toDegrees(double angrad)
          Converts an angle measured in radians to the equivalent angle measured in degrees.
static double toRadians(double angdeg)
          Converts an angle measured in degrees to the equivalent angle measured in radians.
 

Επίλυση δευτεροβάθμιας εξίσωσης

import gr.aueb.dds.BIO;

/*
 * Solve a qudratic equation ax^2 + bx + c = 0
 * Demonstrates the use of math calculations, functions, case analysis
 */
class Quadratic {
        public static void main(String args[]) {
                double a, b, c;         // Equation factors
                double d;               // Discriminant

                BIO.print("a=");
                a = BIO.readDouble();
                BIO.print("b=");
                b = BIO.readDouble();
                BIO.print("c=");
                c = BIO.readDouble();

                if (a == 0) {
                        if (b == 0) {
                                BIO.println("No solutions");
                        } else {
                                // Not really quadratic; one root
                                BIO.print("r=");
                                BIO.println(-c / b);
                        }
                } else {
                        // One complex, one, or two roots
                        d = b * b - 4 * a * c;
                        if (d < 0) {
                                // Complex root
                                BIO.print("r=");
                                // Real part
                                BIO.print(-b / 2 / a);
                                BIO.print("+");
                                // Imaginary part
                                BIO.print(Math.sqrt(-d) / 2 / a);
                                BIO.println("i");
                        } else if (d == 0) {
                                // Two equal roots
                                BIO.print("r1=r2=");
                                BIO.println(-b / 2 / a);
                        } else {
                                // Two different real roots
                                BIO.print("r1=");
                                BIO.println((-b + Math.sqrt(d)) / 2 / a);
                                BIO.print("r2=");
                                BIO.println((-b - Math.sqrt(d)) / 2 / a);
                        }
                }
        }
}

Σημείωση

Στην πράξη ο παραπάνω κώδικας είναι αριθμητικά ασταθής. Για να λύσουμε τη δευτεροβάθμια εξίσωση:
a x2 + b x + c = 0
αν η τιμή του a ή του c ή και των δύο είναι πολύ μικρή τότε μια από τις ρίζες περιλαμβάνει την αφαίρεση δύο σχεδόν ίσων αριθμών (του β και της διακρίνουσας) και το αποτέλεσμα δε θα είναι ακριβές. Για το λόγο αυτό υπολογίζουμε τις δύο ρίζες ως εξής:
double sign , q;

if (b < 0) {
        sign = -1.0;
else {
        sign = 1.0;
}
q = -(b + sign * d) / 2.0;
x1 = q / a;
x2 = c / q;

Εύρεση του μέγιστου αριθμού

import gr.aueb.dds.BIO;

/*
 * Read numbers until 0 is entered.
 * Print the maximum number read.
 * Demonstrates the use of a variable to hold the temporary maximum value
 */
class FindMax {
        public static void main(String args[]) {
                double val;
                double maxVal = -1e308;         // Very small number

                while ((val = BIO.readDouble()) != 0)
                        if (val > maxVal)
                                maxVal = val;
                BIO.println(maxVal);
        }
}

Μετρητής λέξεων

import gr.aueb.dds.BIO;

/*
 * Count number of words.
 * We define a word as a sequence of latin alphabetic characters.
 * Demonstrates the use of toggle variables to hold state.
 */
class WordCount {
        public static void main(String args[]) {
                int code;
                char c;
                boolean inWord = false;         // True when scanning a word
                int count = 0;

                while ((code = BIO.readChar()) != -1) {
                        c = (char)code;
                        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
                                // Word character
                                if (!inWord)
                                        inWord = true;
                        } else {
                                // Non word character
                                if (inWord) {
                                        // A word just finished
                                        inWord = false;
                                        count++;
                                }
                        }
                }
                BIO.println(count);
        }
}

Έλεγχος ISBN

import gr.aueb.dds.BIO;

/*
 * Read an ISBN number and verify if its checksum is ok.
 * Demonstrates conversion of characters to integers, post-decrement,
 * checksums.
 */
class Isbn {
        public static void main(String args[]) {
                int count = 10;         // Digit count and weight
                int sum = 0;            // Checksum
                int code, value;
                char c;

                while (count > 0) {
                        code = BIO.readChar();
                        if (code == -1) {
                                BIO.println("Short ISBN");
                                return;
                        }
                        c = (char)code;
                        // Integer representation of the digit
                        if (c == 'X')
                                value = 10;
                        else
                                // Should use Character.digit(c, 10)
                                value = c - '0';
                        if (value < 0 || value > 10) {
                                BIO.println("Bad ISBN character");
                                return;
                        }
                        sum = sum + value * count--;
                }
                if (sum % 11 == 0)
                        BIO.println("ISBN checks ok");
                else
                        BIO.println("ISBN is wrong");
        }
}

Εξηγήσεις

Ζάρια

import gr.aueb.dds.BIO;

/*
 * Dice thrower
 * Demonstrates random number, functions, character graphics
 */
class Dice {

        /*
         * Calculate a random dice throw and display it as follows:
         * 1-3:
         *        #            #
         *   #                 #
         *             #       #
         * 4-6:
         * #   #   #   #     #    #
         *           #       #    #
         * #   #   #   #     #    #
         */
        static void dice() {
                int n = (int)(Math.random() * 6) + 1;

                BIO.println("[" + n + "]");
                BIO.println();
                // Top row
                // Left
                if (n == 2 || n >= 4) BIO.print("* "); else BIO.print("  ");
                // Middle
                if (n == 3) BIO.print("* "); else BIO.print("  ");
                // Right
                if (n >= 4) BIO.println("* "); else BIO.println("  ");

                // Middle row
                // Left
                if (n == 6) BIO.print("* "); else BIO.print("  ");
                // Middle
                if (n % 2 == 1) BIO.print("* "); else BIO.print("  ");
                // Right
                if (n == 6) BIO.println("* "); else BIO.println("  ");

                // Bottom row
                // Left
                if (n >= 4) BIO.print("* "); else BIO.print("  ");
                // Middle
                if (n == 3) BIO.print("* "); else BIO.print("  ");
                // Right
                if (n == 2 || n >= 4) BIO.println("* "); else BIO.println("  ");
                BIO.println();
        }

        /*
         * Clear the screen by displaying 25 empty lines
         */
        static void clearScreen() {
                int i;

                i = 0;
                while (i < 25) {
                        BIO.println();
                        i++;
                }
        }

        public static void main(String args[]) {
                int code;

                while ((code = BIO.readChar()) != -1) {
                        clearScreen();
                        dice();
                        BIO.println();
                        BIO.println();
                        BIO.println();
                        dice();
                        BIO.println();
                }
        }
}

Αποσφαλμάτωση

Όσο τα προγράμματα που γράφουμε γίνονται πιο περίπλοκα αναγκαζόμαστε να χρησιμοποιούμε διάφορες τεχνικές για την αποσφαλμάτωσή τους. Μερικές από αυτές είναι: Το παρακάτω πρόγραμμα περιέχει εντολές εκτύπωσης κάτω από τον έλεγχο της μεταβλητής debug.
import gr.aueb.dds.BIO;

/*
 * Solve a qudratic equation ax^2 + bx + c = 0
 * Demonstrates the use of debug print statements
 */
class Quadratic {
        public static void main(String args[]) {
                double a, b, c;         // Equation factors
                double d;               // Discriminant
                boolean debug;          // True during development, false in production

                debug = false;

                BIO.print("a=");
                a = BIO.readDouble();
                BIO.print("b=");
                b = BIO.readDouble();
                BIO.print("c=");
                c = BIO.readDouble();

                if (debug == true) {
                        BIO.println("a=" + a);
                        BIO.println("b=" + b);
                        BIO.println("c=" + c);
                }
                if (a == 0) {
                        if (debug)
                                BIO.println("a == 0");
                        if (b == 0) {
                                BIO.println("No solutions");
                        } else {
                                // Not really quadratic; one root
                                BIO.print("r=");
                                BIO.println(-c / b);
                        }
                } else {
                        // Zero or two roots
                        if (debug)
                                BIO.println("a != 0");
                        d = b * b - 4 * a * c;
                        if (debug)
                                BIO.println("d=" + d);
                        if (d < 0) {
                                // Complex root
                                BIO.print("r=");
                                // Real part
                                BIO.print(-b / 2 / a);
                                BIO.print("+");
                                // Imaginary part
                                BIO.print(Math.sqrt(-d) / 2 / a);
                                BIO.println("i");
                        } else if (d == 0) {
                                // Two equal roots
                                BIO.print("r1=r2=");
                                BIO.println(-b / 2 / a);
                        } else {
                                BIO.print("r1=");
                                BIO.println((-b + Math.sqrt(d)) / 2 / a);
                                BIO.print("r2=");
                                BIO.println((-b - Math.sqrt(d)) / 2 / a);
                        }
                }
        }
}

Ασκήσεις

  1. Να γράψετε ένα πρόγραμμα που να αφαιρεί τους κωδικούς επισημείωσης (ακολουθίες της μορφής <tag options>) από αρχεία HTML. Το πρόγραμμα θα δέχεται στην είσοδό του HTML και θα παράγει απλό κείμενο χωρίς τις ακολουθίες επισημείωσης.
  2. Εκτελέστε το πρόγραμμα με είσοδο τη σελίδα αυτή, όπως θα την έχετε φυλλάξει από το Web.
  3. Γράψτε ένα πρόγραμμα που να διαβάζει αριθμούς από την είσοδό του μέχρι να συναντήσει το 0. Στο τέλος το πρόγραμμα πρέπει να εμφανίσει τον μέγιστο, τον ελάχιστο και τον μέσο όρο των αριθμών που διάβασε.
  4. Να γράψετε ένα πρόγραμμα που να λύνει ένα σύστημα δύο εξισώσεων με δύο αγνώστους.
    Προτείνετε στοιχεία εισόδου και αναμενόμενα αποτελέσματα για να ελέγξετε το πρόγραμμα.
  5. Να γράψετε ένα πρόγραμμα που να σας επιτρέπει να παίζετε ρουλέτα με τον υπολογιστή. Στην αρχή ξεκινάτε με ένα συγκεκριμένο ποσό στα χέρια σας. Σε κάθε γύρο το πρόγραμμα σας ρωτάει πόσα χρήματα θέλετε να ποντάρετε και σε ποιο νούμερο θέλετε να τα βάλετε (χρησιμοποιήστε -1 για όλα τα μαύρα και -2 για όλα τα κόκκινα). Στη συνέχεια το πρόγραμμα τυπώνει το σημείο που έπεσε η μπίλια (χρησιμοποιήστε γραφικά και τη φαντασία σας για να δείξετε την κίνηση αυτή) καθώς και το αποτέλεσμα για τον παίκτη (κερδισμένος / χαμένος) και τα χρήματα που έχει τώρα στη διάθεσή του. Το παιγνίδι τελειώνει όταν τελειώσουν τα χρήματα του παίκτη.