From 1fe38f90bbfafae7f4d8ab4cc9a351f068d6ac00 Mon Sep 17 00:00:00 2001 From: Peter Gerwinski <peter.gerwinski@hs-bochum.de> Date: Mon, 17 Apr 2023 18:59:09 +0200 Subject: [PATCH] Weitere Beispiele 17.4.2023: Gleitkommazahlen --- 20230417/bs-20230417.txt | 43 +++++++++ 20230417/chardev-2.c | 185 +++++++++++++++++++++++++++++++++++++ 20230417/decode-float-01.c | 18 ++++ 20230417/decode-float-02.c | 20 ++++ 20230417/deriv-01.c | 25 +++++ 20230417/deriv-01.gp | 4 + 20230417/deriv-02.c | 25 +++++ 20230417/deriv-02.gp | 4 + 20230417/deriv-03.c | 25 +++++ 20230417/deriv-03.gp | 4 + 20230417/deriv-04.c | 26 ++++++ 20230417/deriv-04.gp | 4 + 20230417/deriv-05.c | 26 ++++++ 20230417/deriv-05.gp | 4 + 20230417/dgl-01.c | 14 +++ 20230417/dgl-01.gp | 3 + 20230417/sum-10.c | 38 ++++++++ 20230417/sum-11.c | 38 ++++++++ 20230417/sum-12.c | 36 ++++++++ 20230417/sum-13.c | 36 ++++++++ 20 files changed, 578 insertions(+) create mode 100644 20230417/bs-20230417.txt create mode 100644 20230417/chardev-2.c create mode 100644 20230417/decode-float-01.c create mode 100644 20230417/decode-float-02.c create mode 100644 20230417/deriv-01.c create mode 100644 20230417/deriv-01.gp create mode 100644 20230417/deriv-02.c create mode 100644 20230417/deriv-02.gp create mode 100644 20230417/deriv-03.c create mode 100644 20230417/deriv-03.gp create mode 100644 20230417/deriv-04.c create mode 100644 20230417/deriv-04.gp create mode 100644 20230417/deriv-05.c create mode 100644 20230417/deriv-05.gp create mode 100644 20230417/dgl-01.c create mode 100644 20230417/dgl-01.gp create mode 100644 20230417/sum-10.c create mode 100644 20230417/sum-11.c create mode 100644 20230417/sum-12.c create mode 100644 20230417/sum-13.c diff --git a/20230417/bs-20230417.txt b/20230417/bs-20230417.txt new file mode 100644 index 0000000..8e679b1 --- /dev/null +++ b/20230417/bs-20230417.txt @@ -0,0 +1,43 @@ +Gleitkommazahlen, 17.04.2023, 18:12:52 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +https://de.wikipedia.org/wiki/IEEE_754-2008 + +Die Zahl 2.351 · 10^5 +kann man auch 0.2351 · 10^6 +oder 0.02351 · 10^7 +schreiben. + +Welche dieser Varianten ist hinsichtlich Speicherplatz am ineffizientesten? +0.02351 · 10^7 --> benötigt 7 Zeichen für die Mantisse + +Welche dieser Varianten ist hinsichtlich Speicherplatz am effizientesten? +Beide: +2.351 · 10^5 4 Ziffern für die Mantisse (Konvention: immer 1 Ziffer vor dem Komma) +0.2351 · 10^6 4 Ziffern für die Mantisse (Konvention: immer eine 0 vor dem Komma) + +Bei Binärzahlen: + + 1.11011 · 2^101 (Konvention: immer eine 1 vor dem Komma) "normalisierte Zahl" + 0.111011 · 2^110 (Konvention: immer eine 0 vor dem Komma) + +--> Man braucht die Ziffer vor dem Komma nicht mit zu speichern (wegen Konvention). + Wenn vor dem Komma eine 0 steht, muß dahinter eine 1 stehen (wegen Konvention). +--> Wieder beide gleich. (In beiden Fällen brauchen wir nur 5 Binärziffern zu speichern.) + +Standard: IEEE 754 (2008) +Gleitkommazahlen immer normalisiert speichern, die führende 1 nicht mitspeichern. + +Beispiel: Kodierung einer 32-Bit-Gleitkommazahl: +https://upload.wikimedia.org/wikipedia/commons/5/56/IEEE-754-single.svg + +V EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM + +V = Vorzeichen-Bit +E = "Charakteristik" Siehe: https://de.wikipedia.org/wiki/IEEE_754 +M = Mantisse + +Aufgabe: Schreibe ein Progrämmchen, das eine float-Variable lesbar ausgibt, + ohne printf() mit "%f" zu verwenden, also durch Analysieren der Bits. +Die Aufgabe ist erfüllt, wenn wir die Mantisse (mit Vorzeichen) und den (binären) +Exponenten kennen. Um danach die Dezimalzahl korrekt auszugeben, ist auch +Gleitkommaarithmetik sowie printf() mit "%f" (oder besser: "%e") erlaubt. diff --git a/20230417/chardev-2.c b/20230417/chardev-2.c new file mode 100644 index 0000000..c7d58f1 --- /dev/null +++ b/20230417/chardev-2.c @@ -0,0 +1,185 @@ +/* + * chardev.c: Creates a read-only char device that says how many times + * you've read from the dev file + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/fs.h> +#include <asm/uaccess.h> /* for put_user */ + +MODULE_LICENSE("GPL"); + +/* + * Prototypes - this would normally go in a .h file + */ +int init_module(void); +void cleanup_module(void); +static int device_open(struct inode *, struct file *); +static int device_release(struct inode *, struct file *); +static ssize_t device_read(struct file *, char *, size_t, loff_t *); +static ssize_t device_write(struct file *, const char *, size_t, loff_t *); + +struct class *dev_Class; +struct device *chr_dev; + +#define SUCCESS 0 +#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices */ +#define BUF_LEN 80 /* Max length of the message from the device */ + +/* + * Global variables are declared as static, so are global within the file. + */ + +static int Major; /* Major number assigned to our device driver */ +static int Device_Open = 0; /* Is device open? + * Used to prevent multiple access to device */ +static char msg[BUF_LEN]; /* The msg the device will give when asked */ +static char *msg_Ptr; + +static struct file_operations fops = { + .read = device_read, + .write = device_write, + .open = device_open, + .release = device_release +}; + +/* + * This function is called when the module is loaded + */ +int init_module(void) +{ + Major = register_chrdev(0, DEVICE_NAME, &fops); + + if (Major < 0) { + printk(KERN_ALERT "Registering char device failed with %d\n", Major); + return Major; + } + + // Create module class + printk(KERN_INFO "Creating device class ...\n"); + dev_Class = class_create(THIS_MODULE,DEVICE_NAME); + if( dev_Class == NULL) + { + printk( KERN_ALERT "Error! Class couldn't be created!\n" ); + return 1 ; + } + printk( KERN_INFO "Class created!\n" ); + // Create device in /dev/... + printk(KERN_INFO "Creating device\n"); + chr_dev = device_create(dev_Class, NULL, MKDEV(Major,0), NULL, DEVICE_NAME); + + printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major); + printk(KERN_INFO "the driver, create a dev file with\n"); + printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major); + printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n"); + printk(KERN_INFO "the device file.\n"); + printk(KERN_INFO "Remove the device file and module when done.\n"); + + return SUCCESS; +} + +/* + * This function is called when the module is unloaded + */ +void cleanup_module(void) +{ + /* + * Unregister the device + */ + unregister_chrdev(Major, DEVICE_NAME); +} + +/* + * Methods + */ + +/* + * Called when a process tries to open the device file, like + * "cat /dev/mycharfile" + */ +static int device_open(struct inode *inode, struct file *file) +{ + static int counter = 0; + + if (Device_Open) + return -EBUSY; + + Device_Open++; + sprintf(msg, "I already told you %d times Hello world!\n", counter++); + msg_Ptr = msg; + try_module_get(THIS_MODULE); + + return SUCCESS; +} + +/* + * Called when a process closes the device file. + */ +static int device_release(struct inode *inode, struct file *file) +{ + Device_Open--; /* We're now ready for our next caller */ + + /* + * Decrement the usage count, or else once you opened the file, you'll + * never get get rid of the module. + */ + module_put(THIS_MODULE); + + return 0; +} + +/* + * Called when a process, which already opened the dev file, attempts to + * read from it. + */ +static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */ + char *buffer, /* buffer to fill with data */ + size_t length, /* length of the buffer */ + loff_t * offset) +{ + /* + * Number of bytes actually written to the buffer + */ + int bytes_read = 0; + + /* + * If we're at the end of the message, + * return 0 signifying end of file + */ + if (*msg_Ptr == 0) + return 0; + + /* + * Actually put the data into the buffer + */ + while (length && *msg_Ptr) { + + /* + * The buffer is in the user data segment, not the kernel + * segment so "*" assignment won't work. We have to use + * put_user which copies data from the kernel data segment to + * the user data segment. + */ + put_user(*(msg_Ptr++), buffer++); + + length--; + bytes_read++; + } + + /* + * Most read functions return the number of bytes put into the buffer + */ + return bytes_read; +} + +/* + * Called when a process writes to dev file: echo "hi" > /dev/hello + */ +static ssize_t +device_write(struct file *filp, const char *buff, size_t len, loff_t * off) +{ + printk(KERN_ALERT "Sorry, this operation isn't supported.\n"); + return -EINVAL; +} diff --git a/20230417/decode-float-01.c b/20230417/decode-float-01.c new file mode 100644 index 0000000..9eaf2c8 --- /dev/null +++ b/20230417/decode-float-01.c @@ -0,0 +1,18 @@ +#include <stdio.h> +#include <stdint.h> + +#define B 127 + +int main (void) +{ + float G = 6.6743e-11; + uint32_t *g = (uint32_t *) &G; + int8_t sign = !!(*g & (1 << 31)); + uint8_t ch = (*g >> 23); + int ex = ch - B; + int32_t mant = (*g & 0x7fffff) | 0x800000; + if (sign) + mant *= -1; + printf ("%d·2^%d\n", mant, ex); + return 0; +} diff --git a/20230417/decode-float-02.c b/20230417/decode-float-02.c new file mode 100644 index 0000000..ca22690 --- /dev/null +++ b/20230417/decode-float-02.c @@ -0,0 +1,20 @@ +#include <stdio.h> +#include <stdint.h> +#include <math.h> + +#define B 127 + +int main (void) +{ + float G = 6.6743e-11; + uint32_t *g = (uint32_t *) &G; + int8_t sign = !!(*g & (1 << 31)); + uint8_t ch = (*g >> 23); + int ex = ch - B - 23; + int32_t mant = (*g & 0x7fffff) | 0x800000; + if (sign) + mant *= -1; + printf ("%d·2^%d\n", mant, ex); + printf ("= %e\n", mant * pow (2.0, ex)); + return 0; +} diff --git a/20230417/deriv-01.c b/20230417/deriv-01.c new file mode 100644 index 0000000..610980c --- /dev/null +++ b/20230417/deriv-01.c @@ -0,0 +1,25 @@ +#include <stdio.h> + +float f (float x) +{ + return x * x; +} + +float df_a (float x) +{ + return 2.0 * x; +} + +float df_n (float x) +{ + float dx = 0.0000001; + float df = f (x + 0.5 * dx) - f (x - 0.5 * dx); + return df / dx; +} + +int main (void) +{ + for (float x = -3.0; x <= 3.0; x += 0.1) + printf ("%10f%10f%10f%10f\n", x, f (x), df_a (x), df_n (x)); + return 0; +} diff --git a/20230417/deriv-01.gp b/20230417/deriv-01.gp new file mode 100644 index 0000000..109ff33 --- /dev/null +++ b/20230417/deriv-01.gp @@ -0,0 +1,4 @@ +plot "deriv-01.dat" using 1:2 with lines title "f(x)", \ + "deriv-01.dat" using 1:3 with lines title "df_a(x)", \ + "deriv-01.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)" +pause -1 diff --git a/20230417/deriv-02.c b/20230417/deriv-02.c new file mode 100644 index 0000000..14235c9 --- /dev/null +++ b/20230417/deriv-02.c @@ -0,0 +1,25 @@ +#include <stdio.h> + +float f (float x) +{ + return x * x * x; +} + +float df_a (float x) +{ + return 3.0 * x * x; +} + +float df_n (float x) +{ + float dx = 0.1; + float df = f (x + 0.5 * dx) - f (x - 0.5 * dx); + return df / dx; +} + +int main (void) +{ + for (float x = -3.0; x <= 3.0; x += 0.1) + printf ("%11f %11f %11f %11f\n", x, f (x), df_a (x), df_n (x)); + return 0; +} diff --git a/20230417/deriv-02.gp b/20230417/deriv-02.gp new file mode 100644 index 0000000..a0a097a --- /dev/null +++ b/20230417/deriv-02.gp @@ -0,0 +1,4 @@ +plot "deriv-02.dat" using 1:2 with lines title "f(x)", \ + "deriv-02.dat" using 1:3 with lines title "df_a(x)", \ + "deriv-02.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)" +pause -1 diff --git a/20230417/deriv-03.c b/20230417/deriv-03.c new file mode 100644 index 0000000..79665ff --- /dev/null +++ b/20230417/deriv-03.c @@ -0,0 +1,25 @@ +#include <stdio.h> + +float f (float x) +{ + return x * x * x; +} + +float df_a (float x) +{ + return 3.0 * x * x; +} + +float df_n (float x) +{ + float dx = 0.0000001; + float df = f (x + dx) - f (x); + return df / dx; +} + +int main (void) +{ + for (float x = -3.0; x <= 3.0; x += 0.1) + printf ("%11f %11f %11f %11f\n", x, f (x), df_a (x), df_n (x)); + return 0; +} diff --git a/20230417/deriv-03.gp b/20230417/deriv-03.gp new file mode 100644 index 0000000..34059e0 --- /dev/null +++ b/20230417/deriv-03.gp @@ -0,0 +1,4 @@ +plot "deriv-03.dat" using 1:2 with lines title "f(x)", \ + "deriv-03.dat" using 1:3 with lines title "df_a(x)", \ + "deriv-03.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)" +pause -1 diff --git a/20230417/deriv-04.c b/20230417/deriv-04.c new file mode 100644 index 0000000..7534ea5 --- /dev/null +++ b/20230417/deriv-04.c @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <math.h> + +float f (float x) +{ + return pow (3, x); /* = exp (x * log (3)) */ +} + +float df_a (float x) +{ + return log (3) * pow (3, x); +} + +float df_n (float x) +{ + float dx = 0.0000001; + float df = f (x + dx) - f (x); + return df / dx; +} + +int main (void) +{ + for (float x = -3.0; x <= 3.0; x += 0.1) + printf ("%11f %11f %11f %11f\n", x, f (x), df_a (x), df_n (x)); + return 0; +} diff --git a/20230417/deriv-04.gp b/20230417/deriv-04.gp new file mode 100644 index 0000000..18e76f1 --- /dev/null +++ b/20230417/deriv-04.gp @@ -0,0 +1,4 @@ +plot "deriv-04.dat" using 1:2 with lines title "f(x)", \ + "deriv-04.dat" using 1:3 with lines title "df_a(x)", \ + "deriv-04.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)" +pause -1 diff --git a/20230417/deriv-05.c b/20230417/deriv-05.c new file mode 100644 index 0000000..9569a4a --- /dev/null +++ b/20230417/deriv-05.c @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <math.h> + +float f (float x) +{ + return sin (1.0 / x); +} + +float df_a (float x) +{ + return -cos (1.0 / x) / (x * x); /* pow (x, 2) würde exp (x * log (2)) berechnen --> teuer */ +} + +float df_n (float x) +{ + float dx = 0.0000001; + float df = f (x + dx) - f (x); + return df / dx; +} + +int main (void) +{ + for (float x = 0.3; x <= 3.0; x += 0.1) + printf ("%11f %11f %11f %11f\n", x, f (x), df_a (x), df_n (x)); + return 0; +} diff --git a/20230417/deriv-05.gp b/20230417/deriv-05.gp new file mode 100644 index 0000000..122896c --- /dev/null +++ b/20230417/deriv-05.gp @@ -0,0 +1,4 @@ +plot "deriv-05.dat" using 1:2 with lines title "f(x)", \ + "deriv-05.dat" using 1:3 with lines title "df_a(x)", \ + "deriv-05.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)" +pause -1 diff --git a/20230417/dgl-01.c b/20230417/dgl-01.c new file mode 100644 index 0000000..71b4e3f --- /dev/null +++ b/20230417/dgl-01.c @@ -0,0 +1,14 @@ +#include <stdio.h> +#include <math.h> + +int main (void) +{ + float dx = 0.000001; + float y = 1.0; + for (float x = 0.0; x <= 4.0; x += dx) + { + printf ("%10f%10f%10f\n", x, exp (x), y); + y += y * dx; + } + return 0; +} diff --git a/20230417/dgl-01.gp b/20230417/dgl-01.gp new file mode 100644 index 0000000..681b5db --- /dev/null +++ b/20230417/dgl-01.gp @@ -0,0 +1,3 @@ +plot "dgl-01.dat" using 1:2 with lines title "exp(x)", \ + "dgl-01.dat" using 1:3 with lines dashtype "-" title "y(x)" +pause -1 diff --git a/20230417/sum-10.c b/20230417/sum-10.c new file mode 100644 index 0000000..ebdaef4 --- /dev/null +++ b/20230417/sum-10.c @@ -0,0 +1,38 @@ +#include <stdio.h> +#include <math.h> + +/* exp(x) = Summe aller x^n / n! für n = 0 bis Unendlich */ +/* n! = 1 · 2 · 3 · ... · n */ + +int main (void) +{ + float x = 2.0; + printf ("%0.9f\n", exp (x)); + float S = 0.0; + for (int i = 0; i <= 120; i++) + { + float P = 1.0; + float F = 1.0; + for (int j = 1; j <= i; j++) + { + P *= x; + F *= j; + } + S += P / F; + } + printf ("%0.9f\n", S); + S = 0.0; + for (int i = 120; i >= 0; i--) + { + float P = 1.0; + float F = 1.0; + for (int j = 1; j <= i; j++) + { + P *= x; + F *= j; + } + S += P / F; + } + printf ("%0.9f\n", S); + return 0; +} diff --git a/20230417/sum-11.c b/20230417/sum-11.c new file mode 100644 index 0000000..3925247 --- /dev/null +++ b/20230417/sum-11.c @@ -0,0 +1,38 @@ +#include <stdio.h> +#include <math.h> + +/* exp(x) = Summe aller x^n / n! für n = 0 bis Unendlich */ +/* n! = 1 · 2 · 3 · ... · n */ + +int main (void) +{ + float x = 2.0; + printf ("%0.9f\n", exp (x)); + float S = 0.0; + for (int i = 0; i <= 200; i++) + { + float P = 1.0; + float F = 1.0; + for (int j = 1; j <= i; j++) + { + P *= x; + F *= j; + } + S += P / F; + } + printf ("%0.9f\n", S); + S = 0.0; + for (int i = 200; i >= 0; i--) + { + float P = 1.0; + float F = 1.0; + for (int j = 1; j <= i; j++) + { + P *= x; + F *= j; + } + S += P / F; + } + printf ("%0.9f\n", S); + return 0; +} diff --git a/20230417/sum-12.c b/20230417/sum-12.c new file mode 100644 index 0000000..4bd4842 --- /dev/null +++ b/20230417/sum-12.c @@ -0,0 +1,36 @@ +#include <stdio.h> +#include <math.h> + +/* exp(x) = Summe aller x^n / n! für n = 0 bis Unendlich */ +/* n! = 1 · 2 · 3 · ... · n */ + +int main (void) +{ + float x = 2.0; + printf ("%0.9f\n", exp (x)); + float S = 0.0; + for (int i = 0; i <= 200; i++) + { + float acc = 1.0; + for (int j = 1; j <= i; j++) + { + acc *= x; + acc /= j; + } + S += acc; + } + printf ("%0.9f\n", S); + S = 0.0; + for (int i = 200; i >= 0; i--) + { + float acc = 1.0; + for (int j = 1; j <= i; j++) + { + acc *= x; + acc /= j; + } + S += acc; + } + printf ("%0.9f\n", S); + return 0; +} diff --git a/20230417/sum-13.c b/20230417/sum-13.c new file mode 100644 index 0000000..dd3c5a5 --- /dev/null +++ b/20230417/sum-13.c @@ -0,0 +1,36 @@ +#include <stdio.h> +#include <math.h> + +/* exp(x) = Summe aller x^n / n! für n = 0 bis Unendlich */ +/* n! = 1 · 2 · 3 · ... · n */ + +int main (void) +{ + float x = 2.0; + printf ("%0.9f\n", exp (x)); + float S = 0.0; + for (int i = 0; i <= 1000; i++) + { + float acc = 1.0; + for (int j = 1; j <= i; j++) + { + acc *= x; + acc /= j; + } + S += acc; + } + printf ("%0.9f\n", S); + S = 0.0; + for (int i = 1000; i >= 0; i--) + { + float acc = 1.0; + for (int j = 1; j <= i; j++) + { + acc *= x; + acc /= j; + } + S += acc; + } + printf ("%0.9f\n", S); + return 0; +} -- GitLab