Discussion:
Algorithmus gesucht
(zu alt für eine Antwort)
Arno Welzel
2024-06-17 06:10:50 UTC
Permalink
Vor einiger Zeit bin ich an einen programmierbaren Tischrechner in Form
eines Sharp Compet PC-1001 gekommen:

<https://arnowelzel.de/projekte/technikmuseum/rechner/sharp-compet-pc-1001>

Das Ding ist knapp über 50 Jahre alt und basiert auf einer 4-Bit-CPU von
Rockwell. Und hat eine Eigenheit: wenn man Potenzen berechnet, erhält
man seltsame Rundsfehler.

Konkrete Beispiele:

2^2 = 3,999999996
2^3 = 7,999999995
4^2 = 15,99999998
3^3 = 26,99999997

Auffällig ist, dass der Rundungsfehler nicht immer gleich ist. Ebenso
auffällig ist die lange Berechnungsdauer. Das Ding braucht 2 Sekunden
für die Berechnung, während manuelle Berechnungen wie 2*2 oder 4*4 oder
3*3*3 finden ohne erkennbare Verzögerung stattfinden (als Programm
gespeichert und ausgeführt in wenigen 1/10 Sekunden) und auch die
erwarteten Werte von 4, 16 oder 27 liefern.

Welcher Algorithmus könnte dem zugrunde liegen, dass solche Abweichungen
zustande kommen? Mir fällt auf Anhieb kein Weg ein, der so lange dauert
und zudem am Ende Rundungsfehler produziert.
--
Arno Welzel
https://arnowelzel.de
Peter Heitzer
2024-06-17 07:38:39 UTC
Permalink
Post by Arno Welzel
Vor einiger Zeit bin ich an einen programmierbaren Tischrechner in Form
<https://arnowelzel.de/projekte/technikmuseum/rechner/sharp-compet-pc-1001>
Das Ding ist knapp über 50 Jahre alt und basiert auf einer 4-Bit-CPU von
Rockwell. Und hat eine Eigenheit: wenn man Potenzen berechnet, erhält
man seltsame Rundsfehler.
2^2 = 3,999999996
2^3 = 7,999999995
4^2 = 15,99999998
3^3 = 26,99999997
Auffällig ist, dass der Rundungsfehler nicht immer gleich ist. Ebenso
auffällig ist die lange Berechnungsdauer. Das Ding braucht 2 Sekunden
für die Berechnung, während manuelle Berechnungen wie 2*2 oder 4*4 oder
3*3*3 finden ohne erkennbare Verzögerung stattfinden (als Programm
gespeichert und ausgeführt in wenigen 1/10 Sekunden) und auch die
erwarteten Werte von 4, 16 oder 27 liefern.
Welcher Algorithmus könnte dem zugrunde liegen, dass solche Abweichungen
zustande kommen? Mir fällt auf Anhieb kein Weg ein, der so lange dauert
und zudem am Ende Rundungsfehler produziert.
a^b=exp(ln(a)*b) vielleicht?
Das erklärt zumindest die lange Berechnungszeit. Logarithmus und e-Funktion
sind für eine 4-Bit-CPU keine leichte Aufgabe.
--
Dipl.-Inform(FH) Peter Heitzer, ***@rz.uni-regensburg.de
Stefan Reuther
2024-06-17 17:04:28 UTC
Permalink
Post by Peter Heitzer
Post by Arno Welzel
2^2 = 3,999999996
2^3 = 7,999999995
4^2 = 15,99999998
3^3 = 26,99999997
[...]
Post by Peter Heitzer
Post by Arno Welzel
Welcher Algorithmus könnte dem zugrunde liegen, dass solche Abweichungen
zustande kommen? Mir fällt auf Anhieb kein Weg ein, der so lange dauert
und zudem am Ende Rundungsfehler produziert.
a^b=exp(ln(a)*b) vielleicht?
Davon würde ich ausgehen.

Ähnliche Rechenfehler sind mir von QuickBasic bekannt. Das rechnet
Potenzen ebenfalls intern als exp(ln(a)*b), und schafft es dabei, selbst
auf einer Intel-FPU genug Genauigkeit zu verlieren. Auf dem 4-Bitter
wird das tendenziell noch trauriger aussehen.


Stefan
Rolf Bombach
2024-06-17 21:15:27 UTC
Permalink
Post by Stefan Reuther
Post by Peter Heitzer
Post by Arno Welzel
2^2 = 3,999999996
2^3 = 7,999999995
4^2 = 15,99999998
3^3 = 26,99999997
[...]
Post by Peter Heitzer
Post by Arno Welzel
Welcher Algorithmus könnte dem zugrunde liegen, dass solche Abweichungen
zustande kommen? Mir fällt auf Anhieb kein Weg ein, der so lange dauert
und zudem am Ende Rundungsfehler produziert.
a^b=exp(ln(a)*b) vielleicht?
Davon würde ich ausgehen.
Ähnliche Rechenfehler sind mir von QuickBasic bekannt. Das rechnet
Potenzen ebenfalls intern als exp(ln(a)*b), und schafft es dabei, selbst
auf einer Intel-FPU genug Genauigkeit zu verlieren. Auf dem 4-Bitter
wird das tendenziell noch trauriger aussehen.
Fast in allen Sprachen, die nicht speziell für Mathe ausgerichtet
sind, wird die Potenzberechnung über die Logarithmen gemacht.
Dazu komme noch Fallunterscheidungen für das Vorzeichen und für Null,
das macht es auch nicht schneller :-(
Ausnahme Fortran: Dort merkt der Compiler, dass A*A viel schneller
ist als A^2 über Logarithmus und compiliert daher 'A^2' zu A*A.
Genereller Tip: Potenzen zur 2., 3., vielleicht auch 4. einfach
ausschreiben. C = SQRT(A * A + B * B) für Pythagoras.
--
mfg Rolf Bombach
Christian Weisgerber
2024-06-17 23:12:18 UTC
Permalink
Post by Rolf Bombach
Ausnahme Fortran: Dort merkt der Compiler, dass A*A viel schneller
ist als A^2 über Logarithmus und compiliert daher 'A^2' zu A*A.
Wenn die Potenzoperation zum Sprachumfang gehört, ist das ja eine
naheliegende Optimierung.

Das hat mich jetzt neugierig gemacht. C hat keinen Potenzoperator,
nur eine Standardfunktion pow(). Moderne Compiler kennen aber eine
ganze Reihe von Standardfunktionen und ersetzen den Aufruf der
Bibliotheksfunktion gerne mal mit optimiertem eigenen Code. Und
siehe da...

#include <math.h>
double f(double x)
{
return pow(x, 2);
}

... wird von Clang 18 hierzu compiliert:

0: 55 pushq %rbp
1: 48 89 e5 movq %rsp, %rbp
4: f2 0f 59 c0 mulsd %xmm0, %xmm0
8: 5d popq %rbp
9: c3 retq

Also der Aufruf pow(x, 2) kurzerhand durch x * x ersetzt.


Selbst AWK, in der One-true-awk-Implementierung, optimiert seinen
Potenzoperator:

case POWER:
if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
i = ipow(i, (int) j);
else {
errno = 0;
i = errcheck(pow(i, j), "pow");
}
break;

... und hat das schon vor 30 Jahren getan; älteren Code zu suchen
mach ich mir jetzt nicht die Mühe.
--
Christian "naddy" Weisgerber ***@mips.inka.de
Thomas Koenig
2024-06-18 17:37:52 UTC
Permalink
Post by Christian Weisgerber
Post by Rolf Bombach
Ausnahme Fortran: Dort merkt der Compiler, dass A*A viel schneller
ist als A^2 über Logarithmus und compiliert daher 'A^2' zu A*A.
Wenn die Potenzoperation zum Sprachumfang gehört, ist das ja eine
naheliegende Optimierung.
Das hat mich jetzt neugierig gemacht. C hat keinen Potenzoperator,
nur eine Standardfunktion pow(). Moderne Compiler kennen aber eine
ganze Reihe von Standardfunktionen und ersetzen den Aufruf der
Bibliotheksfunktion gerne mal mit optimiertem eigenen Code. Und
siehe da...
#include <math.h>
double f(double x)
{
return pow(x, 2);
}
0: 55 pushq %rbp
1: 48 89 e5 movq %rsp, %rbp
4: f2 0f 59 c0 mulsd %xmm0, %xmm0
8: 5d popq %rbp
9: c3 retq
Also der Aufruf pow(x, 2) kurzerhand durch x * x ersetzt.
Was einerseits sehr gut ist (und gcc macht das genauso),
andererseits möglicherweise ein wenig mit der C-Norm kollidiert.
Wenn es da einen Overflow gibt, dann ist das ein range error,
und dann hängt es von dem Wert von math_errhandling ab, ob
da errno gesetzt werden soll oder nicht (und das tut der
Code hier offensichtlich nicht).

Hm. math_errhandling scheint auf Linux 3 zu sein, also
MATH_ERRNO | MATH_ERREXCEPT . Daher sollte sowohl eine
Überfluß-Ausnahme gesteigert werden (wie man "an overflow
exception is raised" auch immer am besten übersetzt) als auch
errno gesetzt werden, und letzteres tut der Code oben nicht.

Das sehe ich aber eher als Problem der C-Norm als des Compilers
an. Offensichtlich existiert eine Verschwörung von Fortran -
Anhängern, die C seit Jahrzehnten gezielt sabotieren, damit es
für Numerik weiter hinter Fortran hinterherhinkt.

Wer's gerne effizient, aber nicht so portabel möchte, kann bei
gcc (und vermutlich auch clang) stattdessen __builtin_powi(x, 2)
nehmen.
Post by Christian Weisgerber
Selbst AWK, in der One-true-awk-Implementierung, optimiert seinen
if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
i = ipow(i, (int) j);
else {
errno = 0;
i = errcheck(pow(i, j), "pow");
}
break;
Du hast den Source Code zum Original-awk? Oder ist das BSD?
Christian Weisgerber
2024-06-18 20:06:20 UTC
Permalink
Post by Thomas Koenig
Post by Christian Weisgerber
Selbst AWK, in der One-true-awk-Implementierung, optimiert seinen
Du hast den Source Code zum Original-awk? Oder ist das BSD?
https://github.com/onetrueawk/awk

Bei 4.4BSD findet sich im CSRG-Repository eine frühere Inkarnation:
https://github.com/jonathangray/csrg/tree/master/contrib/awk.research
--
Christian "naddy" Weisgerber ***@mips.inka.de
Stefan Reuther
2024-06-18 16:01:43 UTC
Permalink
Post by Rolf Bombach
Post by Stefan Reuther
Post by Peter Heitzer
Post by Arno Welzel
2^2 = 3,999999996
2^3 = 7,999999995
4^2 = 15,99999998
3^3 = 26,99999997
[...]
Post by Peter Heitzer
Post by Arno Welzel
Welcher Algorithmus könnte dem zugrunde liegen, dass solche Abweichungen
zustande kommen? Mir fällt auf Anhieb kein Weg ein, der so lange dauert
und zudem am Ende Rundungsfehler produziert.
a^b=exp(ln(a)*b) vielleicht?
Davon würde ich ausgehen.
Ähnliche Rechenfehler sind mir von QuickBasic bekannt. Das rechnet
Potenzen ebenfalls intern als exp(ln(a)*b), und schafft es dabei, selbst
auf einer Intel-FPU genug Genauigkeit zu verlieren. Auf dem 4-Bitter
wird das tendenziell noch trauriger aussehen.
Fast in allen Sprachen, die nicht speziell für Mathe ausgerichtet
sind, wird die Potenzberechnung über die Logarithmen gemacht.
Die meisten kriegen's trotzdem hin. Dass QuickBasic da Mist macht, weiß
ich, weil ich Beschwerden von Nutzern eines QuickBasic-Programms hatte,
das den Pythagoras als INT(SQR(dx^2+dy^2)) ausrechnet und dabei Mist
rausbekommt. Ich hatte das deswegen mal analysiert: C und Borland Pascal
mit HW-Float keine Probleme, wenige Probleme mit SW-Float. MS BASIC
trotz HW-Float viele Probleme.

(http://phost.de/~stefan/fuelusage.html "Comparison")
Post by Rolf Bombach
Ausnahme Fortran: Dort merkt der Compiler, dass A*A viel schneller
ist als A^2 über Logarithmus und compiliert daher 'A^2' zu A*A.
Genereller Tip: Potenzen zur 2., 3., vielleicht auch 4. einfach
ausschreiben. C = SQRT(A * A + B * B) für Pythagoras.
Das merken aktuelle C-Compiler auch, zumindest für n=2...


Stefan
Thomas Koenig
2024-06-18 16:32:56 UTC
Permalink
Post by Rolf Bombach
Post by Stefan Reuther
Post by Peter Heitzer
Post by Arno Welzel
2^2 = 3,999999996
2^3 = 7,999999995
4^2 = 15,99999998
3^3 = 26,99999997
[...]
Post by Peter Heitzer
Post by Arno Welzel
Welcher Algorithmus könnte dem zugrunde liegen, dass solche Abweichungen
zustande kommen? Mir fällt auf Anhieb kein Weg ein, der so lange dauert
und zudem am Ende Rundungsfehler produziert.
a^b=exp(ln(a)*b) vielleicht?
Davon würde ich ausgehen.
Ähnliche Rechenfehler sind mir von QuickBasic bekannt. Das rechnet
Potenzen ebenfalls intern als exp(ln(a)*b), und schafft es dabei, selbst
auf einer Intel-FPU genug Genauigkeit zu verlieren. Auf dem 4-Bitter
wird das tendenziell noch trauriger aussehen.
Fast in allen Sprachen, die nicht speziell für Mathe ausgerichtet
sind, wird die Potenzberechnung über die Logarithmen gemacht.
Dazu komme noch Fallunterscheidungen für das Vorzeichen und für Null,
das macht es auch nicht schneller :-(
Ausnahme Fortran: Dort merkt der Compiler, dass A*A viel schneller
ist als A^2 über Logarithmus und compiliert daher 'A^2' zu A*A.
Ist sogar noch ein bisschen ausgefeilter:

double precision function hoch5(x)
double precision :: x
hoch5 = x**5
end function hoch5

wird zu

0: f2 0f 10 07 movsd (%rdi),%xmm0
4: 66 0f 28 c8 movapd %xmm0,%xmm1
8: f2 0f 59 c8 mulsd %xmm0,%xmm1
c: f2 0f 59 c1 mulsd %xmm1,%xmm0
10: f2 0f 59 c1 mulsd %xmm1,%xmm0
14: c3 ret

als nur drei Multiplikationen.
Post by Rolf Bombach
Genereller Tip: Potenzen zur 2., 3., vielleicht auch 4. einfach
ausschreiben.
Wenn man z.B. C verwendet, dann kann man für x**4 auch (x*x) *
(x*x) schreiben, das sind dann nur drei Multiplikationen.

Verwendung von pow in C ist komisch, weil die C-Norm Ansprüche
an das Setzen von errno stellt.
Post by Rolf Bombach
C = SQRT(A * A + B * B) für Pythagoras.
In Fortran kann man auch hypot (a, b) verwenden :-)
Arno Welzel
2024-06-17 19:48:06 UTC
Permalink
Post by Peter Heitzer
Post by Arno Welzel
Vor einiger Zeit bin ich an einen programmierbaren Tischrechner in Form
<https://arnowelzel.de/projekte/technikmuseum/rechner/sharp-compet-pc-1001>
Das Ding ist knapp über 50 Jahre alt und basiert auf einer 4-Bit-CPU von
Rockwell. Und hat eine Eigenheit: wenn man Potenzen berechnet, erhält
man seltsame Rundsfehler.
2^2 = 3,999999996
2^3 = 7,999999995
4^2 = 15,99999998
3^3 = 26,99999997
[...]
Post by Peter Heitzer
a^b=exp(ln(a)*b) vielleicht?
Das erklärt zumindest die lange Berechnungszeit. Logarithmus und e-Funktion
sind für eine 4-Bit-CPU keine leichte Aufgabe.
Ja, das ist die Erklärung, danke!

Wenn ich exp(ln(a)*b) auf dem Gerät manuell in Einzelschritten ausrechne
(ln und exp hat das Ding als Funktion), komme ich auf exakt die selben
"krummen" Werte.
--
Arno Welzel
https://arnowelzel.de
Hermann Riemann
2024-06-17 08:28:43 UTC
Permalink
Post by Arno Welzel
Vor einiger Zeit bin ich an einen programmierbaren Tischrechner in Form
<https://arnowelzel.de/projekte/technikmuseum/rechner/sharp-compet-pc-1001>
Das Ding ist knapp über 50 Jahre alt und basiert auf einer 4-Bit-CPU von
Rockwell. Und hat eine Eigenheit: wenn man Potenzen berechnet, erhält
man seltsame Rundsfehler.
2^2 = 3,999999996
2^3 = 7,999999995
4^2 = 15,99999998
3^3 = 26,99999997
Auffällig ist, dass der Rundungsfehler nicht immer gleich ist. Ebenso
auffällig ist die lange Berechnungsdauer. Das Ding braucht 2 Sekunden
für die Berechnung, während manuelle Berechnungen wie 2*2 oder 4*4 oder
3*3*3 finden ohne erkennbare Verzögerung stattfinden (als Programm
gespeichert und ausgeführt in wenigen 1/10 Sekunden) und auch die
erwarteten Werte von 4, 16 oder 27 liefern.
Das 1+1=1,999999998 ist, dürfte
an (float)1+(float)1 in float Darstellung liegen.

(float)2 ** (float)2
braucht länger als (float)2 * (float)2

Bei letzter Ziffer könnte eine Rundung stattgefunden haben
--
<http://www.hermann-riemann.de>
Marcel Mueller
2024-06-17 16:23:36 UTC
Permalink
Post by Hermann Riemann
Das 1+1=1,999999998 ist, dürfte
an (float)1+(float)1 in float Darstellung liegen.
Ähm, dabei gibt es keine Rundungsfehler. Die Zahl 1 ist in sämtlichen
existierenden Float-Formaten exakt.

Und so altes Zeug rechnet tendenziell überhaupt nicht im Dualsystem,
weil er sonst eine halbe Ewigkeit bräuchte, um die Zahl auch nur
anzuzeigen. Zahlsystemumrechnungen sind nämlich durchaus komplex, wenn
die Primfaktoren nicht dieselben sind. Früher war BCD üblich.
Post by Hermann Riemann
(float)2 ** (float)2
braucht länger als (float)2 * (float)2
Naheliegend. Wenn er jemals auch 2**2.5 berechnen können will, kommt er
mit einer Schleife nicht weit. Das geht, wie Peter schon erwähnt hat
immer über den Logarithmus. Daher auch die Rundungsfehler.

Neuere Taschenrechner arbeiten intern mit 2 Stellen mehr als sie jemals
anzeigen. Dadurch fallen Rundungsfehler selten auf.


Marcel
Rolf Bombach
2024-06-17 21:24:49 UTC
Permalink
Post by Hermann Riemann
Das 1+1=1,999999998 ist, dürfte
an (float)1+(float)1 in float Darstellung liegen.
Ähm, dabei gibt es keine Rundungsfehler. Die Zahl 1 ist in sämtlichen existierenden Float-Formaten exakt.
Und so altes Zeug rechnet tendenziell überhaupt nicht im Dualsystem, weil er sonst eine halbe Ewigkeit bräuchte, um die Zahl auch nur anzuzeigen. Zahlsystemumrechnungen sind nämlich durchaus komplex,
wenn die Primfaktoren nicht dieselben sind. Früher war BCD üblich.
Ja, bei der IBM 1620 zum Beispiel. Dem ersten Computer, an dem ich die
Finger nicht nur dran sondern auch drin hatte :-)
Memory adress register vollständig mit BCD-Lämpchen angezeigt, sauber beschriftet
mit ones, tens, hundreds, thousands und ten thousands.

Loading Image...

Sonst UNIVAC, LINC, CDC bis PDP-1 meist ones' component, two's complement gabs auch.
--
mfg Rolf Bombach
Hermann Riemann
2024-06-18 05:47:16 UTC
Permalink
Post by Marcel Mueller
Post by Hermann Riemann
Das 1+1=1,999999998 ist, dürfte
an (float)1+(float)1 in float Darstellung liegen.
Ähm, dabei gibt es keine Rundungsfehler. Die Zahl 1 ist in sämtlichen
existierenden Float-Formaten exakt.
Und so altes Zeug rechnet tendenziell überhaupt nicht im Dualsystem,
Flipflops sind immer dual.

Durch Zusatzschaltung wurde mit 4 Bit 10-ner System gerechnet.

Ich habe es mit altem BS2000 Assenmbler irgendwie geschafft
da Werte 9 bis 15 reinzubringen.
Sowohl Assembler Objektlistin als auch die Testhilfe IDA
haben dann die Ausgabe verweigert.
--
<http://www.hermann-riemann.de>
Thomas Koenig
2024-06-18 16:40:34 UTC
Permalink
Post by Hermann Riemann
Post by Marcel Mueller
Post by Hermann Riemann
Das 1+1=1,999999998 ist, dürfte
an (float)1+(float)1 in float Darstellung liegen.
Ähm, dabei gibt es keine Rundungsfehler. Die Zahl 1 ist in sämtlichen
existierenden Float-Formaten exakt.
Und so altes Zeug rechnet tendenziell überhaupt nicht im Dualsystem,
Flipflops sind immer dual.
Durch Zusatzschaltung wurde mit 4 Bit 10-ner System gerechnet.
Ich habe es mit altem BS2000 Assenmbler irgendwie geschafft
da Werte 9 bis 15 reinzubringen.
AFAIK ist BS2000 doch ein Betriebssystem für IBM Mainframe-
Kompatible, und die haben zwar BCD-Instruktionen, sind aber binär.

Sicher, dass du BS2000 meinst und nicht ein anderes, dezimales
System?
Hermann Riemann
2024-06-18 17:36:16 UTC
Permalink
Post by Thomas Koenig
Post by Hermann Riemann
Post by Marcel Mueller
Post by Hermann Riemann
Das 1+1=1,999999998 ist, dürfte
an (float)1+(float)1 in float Darstellung liegen.
Ähm, dabei gibt es keine Rundungsfehler. Die Zahl 1 ist in sämtlichen
existierenden Float-Formaten exakt.
Und so altes Zeug rechnet tendenziell überhaupt nicht im Dualsystem,
Flipflops sind immer dual.
Durch Zusatzschaltung wurde mit 4 Bit 10-ner System gerechnet.
Ich habe es mit altem BS2000 Assenmbler irgendwie geschafft
da Werte 9 bis 15 reinzubringen.
AFAIK ist BS2000 doch ein Betriebssystem für IBM Mainframe-
Kompatible, und die haben zwar BCD-Instruktionen, sind aber binär.
Für Ziffern 0-9 werden 4 Bit benötigt.
Post by Thomas Koenig
Sicher, dass du BS2000 meinst und nicht ein anderes, dezimales
System?
Ja.

8 Bit CPUs hatten eventuell eine opcode für dezimal adjust,
den ich nie programmiert habe.
--
<http://www.hermann-riemann.de>
Thomas Koenig
2024-06-18 19:37:39 UTC
Permalink
Post by Hermann Riemann
Post by Thomas Koenig
Post by Hermann Riemann
Post by Marcel Mueller
Post by Hermann Riemann
Das 1+1=1,999999998 ist, dürfte
an (float)1+(float)1 in float Darstellung liegen.
Ähm, dabei gibt es keine Rundungsfehler. Die Zahl 1 ist in sämtlichen
existierenden Float-Formaten exakt.
Und so altes Zeug rechnet tendenziell überhaupt nicht im Dualsystem,
Flipflops sind immer dual.
Durch Zusatzschaltung wurde mit 4 Bit 10-ner System gerechnet.
Ich habe es mit altem BS2000 Assenmbler irgendwie geschafft
da Werte 9 bis 15 reinzubringen.
AFAIK ist BS2000 doch ein Betriebssystem für IBM Mainframe-
Kompatible, und die haben zwar BCD-Instruktionen, sind aber binär.
Für Ziffern 0-9 werden 4 Bit benötigt.
Post by Thomas Koenig
Sicher, dass du BS2000 meinst und nicht ein anderes, dezimales
System?
Ja.
Da verstehe ich was nicht.

Ich habe gerade die "Principle of Operations" für die /360 auf.
Im Kapitel "Decimal Arithmetic" findet sich z.B. die AP -
Instruktion (SS-Format, also 6 Bytes). Da steht "All signs and
digits are checked for validity.", und unter "Program Interruptions"
ist "Data" aufgeführt, und wenn ich da nachschaue, finde ich

Data Exception
A data exception is recognized when:
1. The sign or digit codes of operands in decimal
arithmetic or editing operations or in CONVERT TO
BINARY are incorrect.
2. Fields in decimal arithmetic overlap incorrectly.
3. The decimal multiplicand has too many high-
order significant digits.
The operation is terminated. The instruction-length
code is 2 or 3.

Wenn die Siemens-Maschine mit dem BS2000 das Principles of Operations
implementiert hat, dann hätte das also Bruch geben müssen.
Post by Hermann Riemann
8 Bit CPUs hatten eventuell eine opcode für dezimal adjust,
den ich nie programmiert habe.
Oder wie beim 6502 ein Bit... was mit den Interrupt-Routinen
des C64 nicht kompatibel war.
Hermann Riemann
2024-06-18 05:49:30 UTC
Permalink
Post by Marcel Mueller
Post by Hermann Riemann
Das 1+1=1,999999998 ist, dürfte
an (float)1+(float)1 in float Darstellung liegen.
Ähm, dabei gibt es keine Rundungsfehler. Die Zahl 1 ist in sämtlichen
existierenden Float-Formaten exakt.
Nach meiner Erinnerung war mein oder ein Taschenrechner
bei 1+1 anderer Meinung.
Kann das hier mal jemand mit HP35 probieren?
--
<http://www.hermann-riemann.de>
Helmut Fischer
2024-06-18 08:00:11 UTC
Permalink
Post by Hermann Riemann
Nach meiner Erinnerung war mein oder ein Taschenrechner
bei 1+1 anderer Meinung.
Kann das hier mal jemand mit HP35 probieren?
ich kann:

Eingabe Anzeige
1 1
Enter 1
1 1
+ 2

Einer meiner zwei hp35 hat allerdings den bekannten frühen "2.02"
Serienfehler (siehe: <https://www.hpmuseum.org/hp35.htm>, dort Abschnitt
"the bug"):

2.02 2.02
ln .7030975114
e^x 2

Bei den Rechenbeispielen des OP macht der hp35 andere, aber ähnlich
große Fehler und ist etwas schneller (unter 1 s). Rechne ich die
Operationen zurück (also x^(1/y) statt x^y), kommt der Ursprungswert
exakt wieder raus.

Grüße, Helmut
Hermann Riemann
2024-06-18 08:13:18 UTC
Permalink
Rechne ich die Operationen zurück (also x^(1/y) statt x^y),
kommt der Ursprungswert exakt wieder raus.
Nicht exakt, gerundet.
computer haben nur endlich viel Stellen.
Oder sie müssten symbolisch rechnen.
--
<http://www.hermann-riemann.de>
Stefan Ram
2024-06-18 08:33:50 UTC
Permalink
Post by Hermann Riemann
Nach meiner Erinnerung war mein oder ein Taschenrechner
bei 1+1 anderer Meinung.
Kann das hier mal jemand mit HP35 probieren?
Ich besitze keinen HP-35 und habe auch keinen Emulator installiert.
Aber ich konnte eine eingescanntes Handbuch zum HP-35 finden. Dort
werden am Anfang Beispiele mit Grundrechenarten und ganzen Zahlen
vorgeführt und wohl die jeweilige Anzeige abgedruckt. Demnach sollte

[1]
[Enter↑]
[1]
[+]

zu der Anzeige

2.

führen, obwohl genau diese Rechnung dort nicht zu finden ist.

Um 1981 herum habe ich als Verkäufer bei einem Händler für
"Büroelektronik" gearbeitet, der HP-Vertragshändler war,
und diverse HP-Rechner und auch einen HP-Plotter anbot.
Mein Zuständigkeitsgebiet waren aber Commodore-Geräte.

Ich besitze inzwischen auch einige HP-Taschenrechner als Geräte
(keine Emulatoren), aber habe zuletzt in den 90er Jahren etwas
damit programmiert. Daneben habe ich auf meinem Tisch- und
Handrechner Emulatoren. Auf einem Handrechner, der in etwa die Form
und Größe eines realen HP-Taschenrechners hat, sehen die Oberflächen
der Emulatoren natürlich besonders schön (fast real) aus.
Marc Haber
2024-06-18 10:37:17 UTC
Permalink
Post by Stefan Ram
Ich besitze inzwischen auch einige HP-Taschenrechner als Geräte
(keine Emulatoren), aber habe zuletzt in den 90er Jahren etwas
damit programmiert. Daneben habe ich auf meinem Tisch- und
Handrechner Emulatoren. Auf einem Handrechner, der in etwa die Form
und Größe eines realen HP-Taschenrechners hat, sehen die Oberflächen
der Emulatoren natürlich besonders schön (fast real) aus.
Leider ist die Haptik eines Touchscreens doch etwas anders als die
wunderbaren Tasten der schönen alten HP-Taschenrechner.

Grüße
Marc
--
----------------------------------------------------------------------------
Marc Haber | " Questions are the | Mailadresse im Header
Rhein-Neckar, DE | Beginning of Wisdom " |
Nordisch by Nature | Lt. Worf, TNG "Rightful Heir" | Fon: *49 6224 1600402
Peter Heitzer
2024-06-18 11:24:33 UTC
Permalink
Post by Marc Haber
Post by Stefan Ram
Ich besitze inzwischen auch einige HP-Taschenrechner als Geräte
(keine Emulatoren), aber habe zuletzt in den 90er Jahren etwas
damit programmiert. Daneben habe ich auf meinem Tisch- und
Handrechner Emulatoren. Auf einem Handrechner, der in etwa die Form
und Größe eines realen HP-Taschenrechners hat, sehen die Oberflächen
der Emulatoren natürlich besonders schön (fast real) aus.
Leider ist die Haptik eines Touchscreens doch etwas anders als die
wunderbaren Tasten der schönen alten HP-Taschenrechner.
Und auch die Qualität der Tasten war bei den HP Rechnern sehr gut,
im Gegensatz zu den Rechnern von TI, bei denen nach einiger Zeit die
Tasten nur noch prellten :-(
--
Dipl.-Inform(FH) Peter Heitzer, ***@rz.uni-regensburg.de
Andreas Bockelmann
2024-06-19 20:02:59 UTC
Permalink
Post by Peter Heitzer
Post by Marc Haber
Post by Stefan Ram
Ich besitze inzwischen auch einige HP-Taschenrechner als Geräte
(keine Emulatoren), aber habe zuletzt in den 90er Jahren etwas
damit programmiert. Daneben habe ich auf meinem Tisch- und
Handrechner Emulatoren. Auf einem Handrechner, der in etwa die Form
und Größe eines realen HP-Taschenrechners hat, sehen die Oberflächen
der Emulatoren natürlich besonders schön (fast real) aus.
Leider ist die Haptik eines Touchscreens doch etwas anders als die
wunderbaren Tasten der schönen alten HP-Taschenrechner.
Und auch die Qualität der Tasten war bei den HP Rechnern sehr gut,
im Gegensatz zu den Rechnern von TI, bei denen nach einiger Zeit die
Tasten nur noch prellten :-(
Oja, ich erinnere mich. Angefangen hatte das mit meinem TI58c, dann wurde
der erste TI30 mit LCD in der Schule eingeführt. Ich weiß nicht wieviele
Tastaturen ich überarbeitet habe damit ich auf meinem TI58c und die
Klassenkameraden auf ihren TI30 wieder tippen konnten.
--
Mit freundlichen Grüßen | Fußball, Bier und vor allem Glücksspiel
Andreas Bockelmann | erfüllten den Horizont ihres Geistes.
| Sie in Schach zu halten war nicht schwer
| - George Orwell "1984"
Stefan Ram
2024-06-17 18:10:32 UTC
Permalink
Post by Hermann Riemann
Das 1+1=1,999999998 ist, dürfte
an (float)1+(float)1 in float Darstellung liegen.
Meist ist (float)1+(float)1 genau gleich (float)2, da (float)1
und (float)2 binär normalerweise exakt darstellbar sind.

Dies gilt aber nicht für (float)0.1+(float)0.1. Hier ist schon
(float)0.1 nicht mehr exakt darstellbar, aber dies wird bei
der Ausgabe meist so geschönt, daß es nicht erkennbar ist.

Python
|
|>>> print( 1.0 )
|1.0
|>>> print( 1.0 + 1.0 )
|2.0
|>>> print( 0.1 )
|0.1
|>>> print( 0.1 + 0.1 )
|0.2

Mit "Decimal" werden die wirklich intern verwendeten Werte aber
sichtbar:

Python
|
|>>> from decimal import Decimal
|>>> print( Decimal( 1.0 ))
|1
|>>> print( Decimal( 1.0 + 1.0 ))
|2
|>>> print( Decimal( 0.1 ))
|0.1000000000000000055511151231257827021181583404541015625
|>>> print( Decimal( 0.1 + 0.1 ))
|0.200000000000000011102230246251565404236316680908203125

.
Thomas Koenig
2024-06-17 17:37:34 UTC
Permalink
Post by Arno Welzel
Vor einiger Zeit bin ich an einen programmierbaren Tischrechner in Form
<https://arnowelzel.de/projekte/technikmuseum/rechner/sharp-compet-pc-1001>
Das Ding ist knapp über 50 Jahre alt und basiert auf einer 4-Bit-CPU von
Rockwell. Und hat eine Eigenheit: wenn man Potenzen berechnet, erhält
man seltsame Rundsfehler.
Wie schon andere geschrieben haben, vermutlich über ln und exp.

Diese alten Taschenrechner arbeiteten typischerweise mit CORDIC,
siehe https://en.wikipedia.org/wiki/CORDIC .

Und CORDIC auch dafür verantwortlich, dass der 8087 so
endlos lahm war. Mit 65000 Transistoren hätte man in NMOS
auch was vernünftiges machen können - der ARM2 hatte einen
Booth-Multiplizierer drauf und war eine vollwertige CPU mit nur
27000 Transistoren. Der 68881 war in der Hinsicht auch nicht
besser.
Rolf Bombach
2024-06-17 21:31:28 UTC
Permalink
Post by Thomas Koenig
Diese alten Taschenrechner arbeiteten typischerweise mit CORDIC,
siehe https://en.wikipedia.org/wiki/CORDIC .
Danke für den Hinweis, sehr interessant. Lustig finde ich, dass
Volder den CORDIC-Algorithmus auf der Basis einer Formel entwickelt
hat, die er in der 'Gummibibel' gefunden hat. Das ist das fetteste
Buch, das jeder Chemiker im Regal hat. Jeder. So in schwarz-rot-gold.
Post by Thomas Koenig
Und CORDIC auch dafür verantwortlich, dass der 8087 so
endlos lahm war. Mit 65000 Transistoren hätte man in NMOS
auch was vernünftiges machen können - der ARM2 hatte einen
Booth-Multiplizierer drauf und war eine vollwertige CPU mit nur
27000 Transistoren. Der 68881 war in der Hinsicht auch nicht
besser.
Mit 68000 Transistoren hat man ja auch was gemacht :-)
--
mfg Rolf Bombach
Loading...