[gelöst] Wie überschreiten des Wertebereichs richtig abfangen?
-
#include <limits.h> #include <math.h> #include <stdio.h> #include <stdlib.h> int hoch_aux(int *cache, unsigned basis, unsigned exponent) { if(exponent % 2 == 1) { if(hoch_aux(cache, basis, exponent - 1) || *cache > INT_MAX / (double) basis) { return EXIT_FAILURE; } *cache *= basis; } else if(exponent != 0) { static double intmax_sqrt = sqrt(INT_MAX); if(hoch_aux(cache, basis, exponent / 2) || *cache > intmax_sqrt) { return EXIT_FAILURE; } *cache *= *cache; } return EXIT_SUCCESS; } int hoch(int *result, int basis, unsigned exponent) { int cache = 1, err = EXIT_FAILURE; err = hoch_aux(&cache, abs(basis), exponent); cache *= 1 - 2 * (basis < 0 && exponent % 2 == 0); if(err == EXIT_SUCCESS) { *result = cache; } return err; } int main(int argc, char *argv[]) { int x; if(argc == 3 && !hoch(&x, atoi(argv[1]), atoi(argv[2]))) { printf("%d\n", x); } else { return -1; } return 0; }
-
^^mag ja sein dass dein code geht, aber der ist ja wohl viel komplizierter als die anderen vorschläge hier. *fg*
-
Wenn Performance und Fehlerfall-Garantien dich nicht interessieren, kannst du's auf
int hoch_aux(int *cache, unsigned basis, unsigned exponent) { if(exponent == 0) return EXIT_SUCCESS; if(hoch_aux(cache, basis, exponent - 1) || *cache > INT_MAX / (double) basis) { return EXIT_FAILURE; } *cache *= basis; return EXIT_SUCCESS; } int hoch(int *result, int basis, unsigned exponent) { int err; err = hoch_aux(result, abs(basis), exponent); *result *= 1 - 2 * (basis < 0 && exponent % 2 == 0); return err; }
zusammenstreichen, aber ich halte es nicht für sinnvoll, derart dreckige Praktiken zu verbreiten.
-
seldon schrieb:
aber ich halte es nicht für sinnvoll, derart dreckige Praktiken zu verbreiten.
hab's mal ausprobiert, der zweite code tuts nicht bei mir. der erste aber schon.
-
Eh, tschuldigung.
int hoch(int *result, int basis, unsigned exponent) { int err; *result = 1; /* <-- hier */ err = hoch_aux(result, abs(basis), exponent); *result *= 1 - 2 * (basis < 0 && exponent % 2 == 0); return err; }
-
ach du heiliges potenzmittel. erst ein abs, damit der grösser-vergleich geht, dann alles auf 'double' aufblasen und mit dem: *result *= 1 - 2 * (basis < 0 && exponent % 2 == 0) wird am schluss das vorzeichen wiederhergestellt, ne? das ist doch etwas zu umständlich, finde ich. *fg*
-
Erstens ist abs beim besten Willen kein komplexes Konstrukt. Zweitens wird nichts auf double aufgeblasen, ich benutze nur einen Cast, um eine Integer-Division zu umgehen. Wo ich mir das grad so ankucke, ist das aber eigentlich nicht mal notwendig. Drittens, wenn dir das Zerlegen eines Problems in einfachere Teilprobleme zu hoch ist, solltest du die Wahl deiner beruflichen Laufbahn überdenken, denn als Programmierer hast du dann keine Zukunft.
Im Übrigen hat diese Lösung den Vorteil, dass ihr Verhalten definiert ist. Das ist bei allen, die erst einen Overflow provozieren und danach prüfen, ob einer aufgetreten ist, nicht der Fall (vgl. 3.4.3 im C99-Standard).
-
seldon schrieb:
Drittens, wenn dir das Zerlegen eines Problems in einfachere Teilprobleme zu hoch ist, solltest du die Wahl deiner beruflichen Laufbahn überdenken, denn als Programmierer hast du dann keine Zukunft.
na, da hab ich ja glück, dass ich nur nebenbei programmieren darf. übrigens können wir uns die hand reichen, deine vorzeichen-rekonstruktion tut's nämlich auch nicht so richtig. *fg*
seldon schrieb:
Im Übrigen hat diese Lösung den Vorteil, dass ihr Verhalten definiert ist. Das ist bei allen, die erst einen Overflow provozieren und danach prüfen, ob einer aufgetreten ist, nicht der Fall (vgl. 3.4.3 im C99-Standard).
ich hab doch weiter oben ein .pdf gepostet. da steht z.b. auch drin, wie man overflows vor der multiplikation abfangen kann.