my_exp() und my_log() machen nicht-nachvollziehbaren Mist

Mupfel

Mitglied
Kann mir einer verraten, was an my_log() und my_exp() falsch ist? Ich bekomme untenstehende Werte dabei heraus. Dabei hatte ich extra im Forster nachgeschaut, wie die Reihenentwicklungen sind. my_log() müsste eigentlich zumindest für irgendwelche Werte zwischen 0 und 1 Ergebnisse liefern.

C:
#include <stdio.h>

long double my_exp(double exponent) {
  long long zaehler = 1;
  long double nenner = 1;
  long double summe = 1;
  for (int i = 1; i < 10000; i++) {
    zaehler *= exponent;
    nenner *= i;
    summe += zaehler / nenner;
  }
  return summe;
}

long double my_log(double x) {
  x -= 1.0; // edited
  long double vorzeichen = 1;
  long double summe = x;
  long double potenz = x;
  for (int i = 2; i < 10; i++) {
    potenz *= x;
    vorzeichen *= -1;
    summe += vorzeichen * potenz / i;
    printf("%le\t", summe);
  }
  return summe;
}

long double my_pow(double basis, double exponent) { return my_exp(my_log(basis) * exponent); }

int main(void) {
  printf("exp\n");
  for (int i = 0; i < 10; i++) {
    printf("%le\n", my_exp(i));
  }
  printf("log\n");
  for (int i = 0; i < 10; i++) {
    printf("%le\n", my_log(i / 5.0));
  }
  printf("pow 2\n");
  for (int i = 0; i < 10; i++) {
    printf("%le\n", my_pow(2, i));
  }
}

Ausgabe:
Code:
exp
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
log
4.940656e-324    4.940656e-324    4.940656e-324    4.940656e-324    4.940656e-324    4.940656e-3244.940656e-324    4.940656e-324    1.976263e-323
6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-3106.953204e-310    6.953204e-310    1.976263e-323
6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-3106.953204e-310    6.953204e-310    1.976263e-323
6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-3106.953204e-310    6.953204e-310    1.976263e-323
6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-3106.953204e-310    6.953204e-310    1.976263e-323
6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-3106.953204e-310    6.953204e-310    1.976263e-323
6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-3106.953204e-310    6.953204e-310    1.976263e-323
6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-3106.953204e-310    6.953204e-310    1.976263e-323
6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-3106.953204e-310    6.953204e-310    1.976263e-323
6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-310    6.953204e-3106.953204e-310    6.953204e-310    1.976263e-323
pow 2
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    0.000000e+00    -0.000000e+00
 
Ich fass' mir an den Kopf. Ich habe klein "l" und groß "L" bei printf() verwechselt. clang hat's mir dann verraten.
Für log() habe ich noch keine allgemeine Funktion gefunden. Kennt hier einer eine? Die Reihe ist nur für 0 < x < 2 definiert.

bis auf my_pow() funktioniert's:
C:
#include <stdio.h>

long double my_exp(long double exponent) {
  long long zaehler = 1;
  long double nenner = 1;
  long double summe = 1;
  for (int i = 1; i < 10000; i++) {
    zaehler *= exponent;
    nenner *= i;
    summe += zaehler / nenner;
  }
  return summe;
}

long double my_log(long double x) {
  x -= 1.0; // edited
  long double vorzeichen = 1;
  long double summe = x;
  long double potenz = x;
  for (int i = 2; i < 10000; i++) {
    potenz *= x;
    vorzeichen *= -1;
    summe += vorzeichen * potenz / i;
    //printf("%Le\t", summe);
  }
  return summe;
}

long double my_big_log(long double x) {
  if (x >= 2.0L) {
    return -my_log(1 - (x - 1) / x);
  } else if (x < 2.0L && x > 0.0L) {
    return my_log(x);
  } else {
    printf("range error in my_big_log()");
  }
  return -1;
}

long double my_pow(long double basis, long double exponent) { return my_exp(exponent * my_big_log(basis)); }

int main(void) {
  printf("exp\n");
  for (int i = 0; i < 10; i++) {
    printf("%Le\n", my_exp(i));
  }
  printf("log\n");
  for (int i = 1; i < 10; i++) {
    printf("%Le\n", my_big_log(i));
  }
  printf("pow 2\n");
  for (long double i = 0.0L; i < 10.0L; i++) {
    printf("%Le\n", my_pow(2.0L, i));
  }
}
 
Zuletzt bearbeitet:
Ändere in deiner my_exp Funktion long long zaehler = 1 in long double zaehler = 1, sonst geht die Präzision in zaehler *= exponent verloren.
Und reduzieren deine Schleifendurchläufe auf z.B. 40 sonst läufst du da auch aus der Darstellungsgrenze von long double raus und kriegst ungültige Werte.
 
Zurück
Oben Unten