Forum: Mikrocontroller und Digitale Elektronik sprintf: was ist falsch?


von Maxim B. (max182)


Lesenswert?

Guten Tag!

Ich habe immer selbst gebaute Funktionen für Ausgabe benutzt. Nun wollte 
ich sprintf ausprobieren.
1
#include <avr/io.h>
2
#include <math.h>
3
#include <stdio.h>
4
5
#include "main.h" 
6
7
char buff[20] = {0};
8
char b = 0;
9
10
int main(void){
11
12
asm volatile("nop");
13
b = sprintf(buff, "%f", 12.234657);
14
asm volatile("nop");
15
16
return 0;
17
}
In buff bekomme ich '?', d.h. 0x3f. In b, wie auch sein sollte, 1.
Ich habe aber für anderes in buff gerechnet.
Was fehlt hier noch?

mit "%d" und integer bekomme ich richtige Ausgabe. Aber min "%f" will 
sprintf nicht arbeiten.

Vielen Dank für die Antwort im voraus!

von A. S. (Gast)


Lesenswert?

oftmals muss man gesondert angeben, dass man Floating-Point will. In den 
Compiler-Options oder auch bei der Auswahl der zu linkenden Library.

Floating point ist für Micro-Microkontroller halt aufwendig.

von bdugfgj (Gast)


Lesenswert?

Ja, floatingpoint Support der Library aktivieren. Als Tipp noch die n 
Versionen der printf Familie verwenden. Also z.B. snprintf.

von Maxim B. (max182)


Lesenswert?

Ich habe zu Testzwecken auch mit float hantiert. #include <math.h> war 
genug, um * und / korrekt gemacht wurden. Das konnte ich in 
Watch-Fenster von AVR Studio sehen. Nur mit sprintf funktioniert es mit 
float nicht. Warum?

von bdugfgj (Gast)


Lesenswert?

Hast du die beiden Antworten über deiner gelesen?

von Maxim B. (max182)


Lesenswert?

ich habe Arithmetik mit float ausprobiert. #include <math.h> reichte 
dafür. D.h. float ist aktiviert. Problem nur mit sprintf.

Mit snprintf ist Problem gleich.

Auch Anbinden von libm.a hat nichts gebracht.

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Maxim B. schrieb:
> Problem nur mit sprintf.
>
> Mit snprintf ist Problem gleich.

Die ersten beiden Antworten nochmal lesen.
So oft, bis verstanden.

von Maxim B. (max182)


Lesenswert?

Arduino Fanboy D. schrieb:
> Die ersten beiden Antworten nochmal lesen.
> So oft, bis verstanden.

Danke für Info. Sehr hilfreich. Deine Antwort enthält sehr viel 
nutzbarer Information.

: Bearbeitet durch User
von bdugfgj (Gast)


Lesenswert?

Maxim B. schrieb:
> Arduino Fanboy D. schrieb:
> Die ersten beiden Antworten nochmal lesen.
> So oft, bis verstanden.
>
> Danke für Info. Sehr hilfreich.

Wenn dich drei Leute bereits auf das selbe hinweisen und du es nicht 
verstehst, solltest du vllt erst Mal über dich selber nachdenken.

von Maxim B. (max182)


Lesenswert?

bdugfgj schrieb:
> Wenn dich drei Leute bereits auf das selbe hinweisen

Floatingpoint Support der Library aktiviert. Noch die n
Versionen der printf Familie verwendet. Alles bleibt gleich. Was könnte 
ich noch machen?

ich habe (fast) gleiche Code (ohne AVR-spezifischen und mit printf) mit 
Dev-C++ getestet: alles ist gut mit Float. Nur mit GCC das Problem.

: Bearbeitet durch User
von 2⁵ (Gast)


Lesenswert?

Verstehst du Englisch: Hier ist das Vorgehen mit AVR Studio 7 erklärt:
https://startingelectronics.org/articles/atmel-AVR-8-bit/print-float-atmel-studio-7/

von Einer K. (Gast)


Lesenswert?

Maxim B. schrieb:
> Deine Antwort enthält sehr viel
> nutzbarer Information.

Deine Frage auch!

Mein heiß geliebtes Arduino möchte zur Aktivierung des %f in printf 
folgende Zeile in der betreffenden platforms.local.txt sehen:
> compiler.c.elf.extra_flags=-Wl,-u,vfprintf -lprintf_flt -lm
Wie du es deinem geheimen System vorkauen musst, kann ich dir nicht 
sagen.

von Maxim B. (max182)


Lesenswert?

2⁵ schrieb:
> Verstehst du Englisch:

leider kaum.

> Hier ist das Vorgehen mit AVR Studio 7 erklärt:

ich benutze AVR-Studio 4.19. Mit meinem COmputer geht das viel sicherer 
als AVR Studio 7.

von leo (Gast)


Lesenswert?

Maxim B. schrieb:
> Floatingpoint Support der Library aktiviert.

Floatingpoint Support fuer sprintf aktivieren war wohl genauer gemeint.

leo

von Einer K. (Gast)


Lesenswert?


von Maxim B. (max182)


Lesenswert?

leo schrieb:
> Floatingpoint Support fuer sprintf aktivieren war wohl genauer gemeint.

Könntest du das bitte ausführlicher erklären?

von Maxim B. (max182)


Lesenswert?

Arduino Fanboy D. schrieb:
> Oder einfach mal die Doku lesen, da stehts auch drin....
> 
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1

Dort steht nichts anderes als im Buch von Herbert Schildt. Aber die 
Beispiele von Schildt arbeiten auch nicht korrekt.

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Arduino Fanboy D. schrieb:
>> compiler.c.elf.extra_flags=-Wl,-u,vfprintf -lprintf_flt -lm
> Wie du es deinem geheimen System vorkauen musst, kann ich dir nicht
> sagen.

Auch mit -lm nichts geändert.

Vielleiicht sollte ich noch Version von GCC sagen: 5.4.0

Auch die Frage: wie kann das sein, dass float alle Operationen korrekt 
lassen, nur mit sprintf das Problem? Wäre float nicht aktiviert, so 
könnte sicher auch Multiplizieren nicht gelingen oder?

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Maxim B. schrieb:
> Vielleiicht sollte ich noch Version von GCC sagen: 5.4.0

5.4, 7.3, 9.1
Funktioniert mit allen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Maxim B. schrieb:
> Auch mit -lm nichts geändert.

Und was ist mit

  -Wl,-u,vfprintf

und

  -lprintf_flt

Könnten diese Optionen evtl. etwas mit printf und Konsorten zu tun
haben? ;-)

von Einer K. (Gast)


Lesenswert?

Maxim B. schrieb:
> Auch die Frage: wie kann das sein, dass float alle Operationen korrekt
> lassen, nur mit sprintf das Problem? Wäre float nicht aktiviert, so
> könnte sicher auch Multiplizieren nicht gelingen oder?

Du hast die Doku noch nicht gelesen:
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1

Da steht: (ich lese es dir mal vor)

Since the full implementation of all the mentioned features becomes 
fairly large, three different flavours of vfprintf() can be selected 
using linker options. The default vfprintf() implements all the 
mentioned functionality except floating point conversions. A minimized 
version of vfprintf() is available that only implements the very basic 
integer and string conversion facilities, but only the # additional 
option can be specified using conversion flags (these flags are parsed 
correctly from the format specification, but then simply ignored). This 
version can be requested using the following compiler options:

    1 -Wl,-u,vfprintf -lprintf_min
If the full functionality including the floating point conversions is 
required, the following options should be used:

von leo (Gast)


Lesenswert?

Maxim B. schrieb:
> 
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1
>
> Dort steht nichts anderes als

Du sollst vielleicht weiter lesen auf der Seite bis zum Ende.

leo

von S. R. (svenska)


Lesenswert?

Maxim B. schrieb:
> Auch mit -lm nichts geändert.

Du sollst nicht "float für Mathematik" anschalten.

Du sollst "float für printf" anschalten.
Dazu brauchst du eine andere printf-Bibliothek.

von S. R. (svenska)


Lesenswert?

Arduino Fanboy D. schrieb:
> Da steht: (ich lese es dir mal vor)

Wenn er des Englischen nicht mächtig ist, dann hilft das leider nicht 
viel. Ein bisschen Rücksicht muss man manchmal auch nehmen.

von Einer K. (Gast)


Lesenswert?

S. R. schrieb:
> Wenn er des Englischen nicht mächtig ist, dann hilft das leider nicht
> viel.

Ich glaube, es hakt an anderer Stelle.

von S. R. (svenska)


Lesenswert?

Arduino Fanboy D. schrieb:
>> Wenn er des Englischen nicht mächtig ist,
>> dann hilft das leider nicht viel.
>
> Ich glaube, es hakt an anderer Stelle.

Zum Beispiel daran, dass du den relevanten Teil garnicht kopiert hast?

von Maxim B. (max182)


Lesenswert?

Alle Optionen, die z.Z. stehen:
-Wall
-gdwarf-2
-std=gnu99
-gstrict-dwarf
-lprintf_flt
-lm
-Wl,-u,vfprintf
-lprintf_flt
-DF_CPU=8000000UL
-Os
-funsigned-char
-funsigned-bitfields
-fpack-struct
-fshort-enums

Auch libc.a und libm.a angeschlossen.

von Maxim B. (max182)


Lesenswert?

S. R. schrieb:
> Du sollst nicht "float für Mathematik" anschalten.
>
> Du sollst "float für printf" anschalten.
> Dazu brauchst du eine andere printf-Bibliothek.

Kannst du bitte sagen, welche? Wie heißt sie, wo sie ist?

von S. R. (svenska)


Lesenswert?

Maxim B. schrieb:
> Kannst du bitte sagen, welche? Wie heißt sie, wo sie ist?

Du hast sie bereits angeschaltet:

Maxim B. schrieb:
> -lprintf_flt
> -lm
> -Wl,-u,vfprintf

Wenn es also noch immer nicht funktioniert, dann liegt das daran, dass 
diese Parameter nicht benutzt werden. Das können wir von hier nicht 
feststellen, also prüfe deine Umgebung.

Du kannst zum Testen ja ein "-fkjdsfhdylfgdl" ranhängen.
Das muss einen Fehler bringen.

von Rolf M. (rmagnus)


Lesenswert?

Maxim B. schrieb:
> Arduino Fanboy D. schrieb:
>> Oder einfach mal die Doku lesen, da stehts auch drin....
>>
> 
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1
>
> Dort steht nichts anderes als im Buch von Herbert Schildt. Aber die
> Beispiele von Schildt arbeiten auch nicht korrekt.

Das Buch von Schildt enthält Infos darüber, wie man bei der von dir 
geheim gehaltenen Toolchain Floatingpoint-Support für printf 
aktiviert? Das würde mich sehr wundern.

Maxim B. schrieb:
> Arduino Fanboy D. schrieb:
>>> compiler.c.elf.extra_flags=-Wl,-u,vfprintf -lprintf_flt -lm
>> Wie du es deinem geheimen System vorkauen musst, kann ich dir nicht
>> sagen.
>
> Auch mit -lm nichts geändert.
>
> Vielleiicht sollte ich noch Version von GCC sagen: 5.4.0

Und jetzt noch, für welche Zielplattform…

> Auch die Frage: wie kann das sein, dass float alle Operationen korrekt
> lassen, nur mit sprintf das Problem? Wäre float nicht aktiviert, so
> könnte sicher auch Multiplizieren nicht gelingen oder?

Weil -lm nur die Float-Bibliothek dazu linkt und nicht printf austauscht 
durch eins, das float unterstüzt. Dazu sind die anderen Optionen da. 
Aber wenn die bei dir nicht funktionieren, ist entweder was kaputt, oder 
du nutzt eine andere Toolchain, bei der die Optionen anders lauten 
müssen.

Arduino Fanboy D. schrieb:
> S. R. schrieb:
>> Wenn er des Englischen nicht mächtig ist, dann hilft das leider nicht
>> viel.
>
> Ich glaube, es hakt an anderer Stelle.

Den Eindruck habe ich auch.

von Maxim B. (max182)


Lesenswert?

Arduino Fanboy D. schrieb:
> If the full functionality including the floating point conversions is
> required, the following options should be used:

 -Wl,-u,vfprintf -lprintf_flt -lm
in Linker-Optionen !!!

Das wars!!!!
Alles in Ordnung. Das fehlte mir hier.

Vielen Dank!!!

: Bearbeitet durch User
von S. R. (svenska)


Lesenswert?

Rolf M. schrieb:
>> Ich glaube, es hakt an anderer Stelle.
> Den Eindruck habe ich auch.

Die wesentlichen Informationen sind ja gegeben:
- AVR Studio 4.19
- GCC 5.4.0
- kein Englisch.

Maxim ist ein Organist, der ein bisschen mit AVR bastelt.
Kein bisschen Ingeneurshintergrund.

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

S. R. schrieb:
> Maxim ist ein Organist, der ein bisschen mit AVR bastelt.
> Kein bisschen Ingeneurshintergrund.

Ja. Einfach etwas Abschaltung von Musik. Das macht mir viel Spaß. Viel 
mehr Ahnung habe ich für Klavier- und Orgelbau und -Stimmung.

Z.Z überlege ich, ob es möglich ist mit meinen Vorkenntnissen, 
TLA-Stimmgerät nachzubauen (wer das Gerät nicht kennt: es kostet wie 
zwei Laptops. ich habe zwar ein, aber...). Dort sind float und double 
sehr wichtig. Eine Experimentierplatine für ATMEGA1284P habe ich mir 
entworfen, mit JTAG, nach Modulprinzip, so kann ich lange damit 
experimentieren.

Leider sind ansonsten bequeme billige Platten von Arduino Mega2560 kaum 
zu gebrauchen: dort sind wie mit Absicht von allen vier USART keine 
XCK-Leitungen gemacht. D.h. USART kann man nicht in SPI-Mode benutzen.

: Bearbeitet durch User
Beitrag #5927926 wurde von einem Moderator gelöscht.
von S. R. (svenska)


Lesenswert?

Maxim B. schrieb:
> Dort sind float und double sehr wichtig.

Dann kannst du den ATMega nicht benutzen, denn der kann kein double.
Du kannst zwar "double" hinschreiben, aber er nimmt trotzdem float.

von Rolf M. (rmagnus)


Lesenswert?

Erstmal müsst man schauen, ob double wirklich benötigt wird. Oft kommt 
man mit Festkommaarithmetik schon sehr weit.

von Maxim B. (max182)


Lesenswert?

S. R. schrieb:
> Dann kannst du den ATMega nicht benutzen, denn der kann kein double.

Doch! ich habe hier in Forum eine Bibliothek gefunden! Dort sind double 
mit Hilde von u64 gemacht.

von Maxim B. (max182)


Lesenswert?

Rolf M. schrieb:
> Oft kommt
> man mit Festkommaarithmetik schon sehr weit.

Das stimmt. Aber manchmal gibt es genug Zeit und man kann bequemere 
Variante wählen.

Als Beispiel: Frequenzmeter (ein Stimmgerät ist nichts anderes als ein 
Frequenzmeter mit guter Auflösung für Schallfrequenzen. 0,001 Hz ist 
gute Wert, schlechter als 0,03 Hz darf das nicht sein). Man macht eine 
Messung, dann wird gerechnet. Dann wieder eine Messung. Dabei ist nicht 
so wichtig, wird 3mal pro Sekunde gemessen oder nur 2,9mal. So hat man 
mehrere Millisekunden für Rechnen.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Maxim B. schrieb:
> Auch mit -lm nichts geändert.

-lm ist überflüssig, das gibt der Compiler ohnehin dem Linker mit.  Und 
zwar immer (außer mit -nostdlib).

> Wäre float nicht aktiviert, so könnte sicher auch Multiplizieren
> nicht gelingen oder?

float-Multiplikation ist Teil des Sprachkerns, das kann man weder 
aktivieren noch deaktivieren, und math.h braucht's auch nicht dazu.

Im Gegensatz dazu kommen sinf(), sprintf() etc. aus Bibliotheken und 
sind in Headern deklariert, der Sprachkern braucht nix davon zu wissen. 
Alles was zu wissen ist, ist das Interface beim Aufruf, und das steht im 
jeweiligen Header.


Maxim B. schrieb:
> TLA-Stimmgerät [...] Dort sind float und double sehr wichtig.

double ist bei avr-gcc nicht standardkonform so wie float implementiert, 
also nur 32 Bits lang.

Ja nachdem, welche Operationen gebraucht werden und wie der 
erforderliche Wertebereich ist, kann Fixed-Point basierend auf uint64_t 
oder uint32_t in Betracht gezogen werden, evtl. auch Fixed-Point aus 
stdfix.h.

Dazu müsste man aber erst die benötigten Operationen / Algorithmen 
kennen.

von Maxim B. (max182)


Lesenswert?

Johann L. schrieb:
> Dazu müsste man aber erst die benötigten Operationen / Algorithmen
> kennen.

Deshalb bin ich hier in Forum :) Um mehr zu wissen. Ich habe zwar vier 
Diplome, aber alle sind musikalisch. Technik muß ich selber lernen.

Ich freue mich sehr, daß hier in Forum auch die Menschen sind, die sich 
die Mühe nicht sparen, etwas zu erklären.

Das mit sprintf, was gelöst wurde - das brauche ich nicht unmittelbar 
für ein Stimmgerät oder so was ähnliches. Dort benutz man besser andere 
Ausgabeformen (Man gibt Abweichung in Cent aus oder/und per Stroboskop). 
Aber ich möchte besser Standardbibliotek kennen. Ich möchte gut 
verstehen, wie alles funktioniert.


Beitrag "64 Bit float Emulator in C, IEEE754 compatibel"

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Johann L. schrieb:
> Im Gegensatz dazu kommen sinf(), sprintf() etc. aus Bibliotheken und
> sind in Headern deklariert,

In der Lib, die mit -lm eingebunden wird, sind die Funktionen aus der 
<math.h>

von S. R. (svenska)


Lesenswert?

Maxim B. schrieb:
>> Dann kannst du den ATMega nicht benutzen, denn der kann kein double.
> Doch! ich habe hier in Forum eine Bibliothek gefunden!

Äh, nein. Der AVR kann kein double. Die avr-libc kann auch kein double.

> Dort sind double mit Hilde von u64 gemacht.

Dann ist das Fließkommaarithmetik auf u64, kein double.

Das funktioniert nicht mit den normalen Bibliotheken, auch nicht mit 
printf!

Das ist ein Unterschied!

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

S. R. schrieb:
> Maxim B. schrieb:
>>> Dann kannst du den ATMega nicht benutzen, denn der kann kein double.
>> Doch! ich habe hier in Forum eine Bibliothek gefunden!
>
> Äh, nein. Der AVR kann kein double.

Er hat keine FPU, die das direkt in Hardware macht. Aber natürlich ist 
es möglich, sowas für den AVR in Software zu implementieren. Es wurde in 
der avr-libc nur nicht gemacht.

S. R. schrieb:
> Dann ist das Fließkommaarithmetik auf u64, kein double.

Es ist das double, das in IEEE 754 spezifiziert ist, nicht der 
C-Datentyp double.

> Das funktioniert nicht mit den normalen Bibliotheken, auch nicht mit
> printf!

Allerdings. Mit dem obigen sprintf("...%f...") kann man das nicht 
ausgeben.

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

S. R. schrieb:
> Das funktioniert nicht mit den normalen Bibliotheken, auch nicht mit
> printf!
>
> Das ist ein Unterschied!

Ja, wenn ich solche double so wie sie sind auf LCD zeigen möchte, dann 
sollte ich selber eine Funktion machen... Nichts unmögliches. Wenigstens 
habe ich integer bisher auch so ausgegeben. Eigengemachte hex-dec ist 
auch viel sparsamer, als sprintf, da addieren und subtrahieren mit AVR 
viel schneller geht als dividieren.
Etwa so:
1
void hex_dec(int zahl, char *puff){
2
     char a=0, b=0, c=0, d=0, e=0;
3
     while(zahl >= 10000){
4
    zahl -= 10000;
5
    a++;
6
  }
7
  while(zahl >= 1000){
8
    zahl -= 1000;
9
    b++;
10
  }
11
  while(zahl >= 100){
12
    zahl -= 100;
13
    c++;
14
  }
15
  while(zahl >= 10){
16
    zahl -= 10;
17
    d++;
18
  }
19
  while(zahl >= 1){
20
    zahl -= 1;
21
    e++;
22
  }
23
  *puff++ = a + 0x30;
24
  *puff++ = b + 0x30;
25
  *puff++ = c + 0x30;
26
  *puff++ = d + 0x30;
27
  *puff = e + 0x30;
28
}

Aber double braucht man vielleicht 2-3 mal für das ganze Programm. Nur 
dort wo es wirklich notwendig. Zum Beispiel um Frequenzwert auf Zeitwert 
zu dividieren und dann Abweichung in Cent berechnen (1 Cent ist Wurzel 
1200 Grad aus 2 ). Es ist üblich, das verschiedene Temperierungen in 
Cent gegen gleichschwebende Stimmung angegeben werden. Deshalb auch 
Anzeige in Cent ist bequem. Für Centausgabe für LCD reicht float aus.

Frequenzberechnungen für Klavierstimmung müssen sehr genau sein, float 
reicht hier nicht. TLA hat unter anderem eine Mode, wo Obertöne auf 
kritischen Seiten gemessen werden und daraus wird Spreizungskurve für 
bestimmten Klavier berechnet. Ich habe diese Mode ausprobiert: 
Stimmgenauigkeit ist kaum schlechter als bei der Stimmung nach Gehör! 
Gewöhnliche Stimmgeräte erreichen das nie. Also, Genauigkeit... 
Verhältnis 1 Cent heißt 1,00057778950... Für a1 bedeutet das 0,25 Hz 
Schwebung, das ist sehr gut hörbar (da die Obertöne um Mehrfaches öfter 
schweben), es sollte viel genauer gestimmt werden - so ist float hier an 
der Grenze, wenn unter 1 Cent zu gehen ist. Aber auch billige 
Stimmgeräte geben 0,1 Cent Differenzen aus...

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Maxim B. schrieb:
>   *puff++ = a + 0x30;
>   *puff++ = b + 0x30;
>   *puff++ = c + 0x30;
>   *puff++ = d + 0x30;
>   *puff = e + 0x30;

Addition von 0x30 ('0') kann man weglassen, wenn man a, b, c, d, e mit 
'0' initialisiert:
1
char a = '0', b = '0', c = '0', d = '0', e = '0';

>   while(zahl >= 10){
>     zahl -= 10;
>     d++;
>   }
>   while(zahl >= 1){
>     zahl -= 1;
>     e++;
>   }

Einfacher:
1
    e += (char) zahl;

> void hex_dec (int zahl, char *puff)

Sollte das nicht "unsigned int zahl" sein (bzw. uint16_t)? Oder es fehlt 
der Fall zahl < 0.

> wenn ich solche double so wie sie sind auf LCD zeigen möchte,
> dann sollte ich selber eine Funktion machen...

Ist hier doch dabei? Als f_to_string() bzw. als f_strtod()

Beitrag "Re: 64 Bit float Emulator in C, IEEE754 compatibel"

von Rolf M. (rmagnus)


Lesenswert?

Maxim B. schrieb:
> Ja, wenn ich solche double so wie sie sind auf LCD zeigen möchte, dann
> sollte ich selber eine Funktion machen... Nichts unmögliches. Wenigstens
> habe ich integer bisher auch so ausgegeben.

Ein Floatingpoint-Format funktionert aber anders. Es ist kein Hexenwerk, 
das auszugeben, aber etwas mehr als in dem von dir geposteten Code ist 
es schon.

> Zum Beispiel um Frequenzwert auf Zeitwert zu dividieren und dann
> Abweichung in Cent berechnen (1 Cent ist Wurzel 1200 Grad aus 2 ).

1200 Grad? Der Frequenz-Faktor eines Cent ist die 1200ste Wurzel aus 2. 
Das ergibt also den Faktor der Frequenzen von zwei Tönen, die um einen 
Cent auseinander liegen.
Wenn du wissen willst, um wieviel Cent sich zwei Frequenzen 
unterscheiden, musst du die Frequenzen durcheinander dividieren und dann 
ermitteln, die wievielte Wurzel daraus ein Cent ist. Du brauchst also 
eine Logarithmusfunktion.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Maxim B. schrieb:
> Aber double braucht man vielleicht 2-3 mal für das ganze Programm. Nur
> dort wo es wirklich notwendig. Zum Beispiel um Frequenzwert auf Zeitwert
> zu dividieren und dann Abweichung in Cent berechnen

Dazu brauchst du keine 64-Bit-Doubles. 32-Floats sind schon um mehrere 
Größenordnungen genauer als es deine Frequenzmessung je sein wird.

Die relative Auflösung von 32-Bit-Float ist 2**(-23), was 0,0002 Cent 
entspricht. Das sollte doch locker reichen, oder?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Wenn du wissen willst, um wieviel Cent sich zwei Frequenzen
> unterscheiden, musst du die Frequenzen durcheinander dividieren und dann
> ermitteln, die wievielte Wurzel daraus ein Cent ist. Du brauchst also
> eine Logarithmusfunktion.

Ist das wirklich notwendig?  Bin zwar kein Musiker... aber es geht ja um 
ein Stimmgerät, d.h. die Frequenz ist nicht arg viel anders als die 
Zielfrequenz.  Das Verhältnis der beiden ist also etwa 1 bzw. das 
Verhältnis lässt sich darstellen als 1 + x mit betragsmäßig kleinem x.
1
log_B (1 + x) = ln (1 + x) / ln (B)
2
              = x / ln (B)     für betragsmäßig kleine x.
und wenn die Abweichung 0 ist, dann ist auch x gleich 0 und der Fehler 
der Approximation ist 0.

Wenn es also nicht notwendig ist, den genauen Fehlerwert anzuzeigen, 
dann tut's auch die Näherung; die übrigens gleiches Vorzeichen hat wie 
log_B (1 + x).

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
> Ist das wirklich notwendig?  Bin zwar kein Musiker...

Ich beschäftige mich zwar etwas mit Musik, würde mich aber nicht als 
Musiker bezeichnen. Aber soweit ich verstehe, ist es notwendig. Es gibt 
in der Musik nicht nur die gleichstufige Stimmung, bei der jeder 
Halbtonschritt genau gleich groß ist. Und nach Maxims obiger Aussage 
werden andere Stimmungen gerne in Cent Abweichung gegenüber einer 
gleichstufigen Stimmung angegeben. Und genau die muss man dann 
erreichen. Das heißt, er muss die Abweichung sehr genau angezeigt 
bekommen, und es reicht nicht, einfach auf 0 zu kommen.
@Maxim: Korrigiere mich, wenn ich hier Blödsinn erzähle.

von Maxim B. (max182)


Lesenswert?

Johann L. schrieb:
> Sollte das nicht "unsigned int zahl" sein (bzw. uint16_t)? Oder es fehlt
> der Fall zahl < 0.

Genau. Vergleich (zahl >= 0) ist dann immer wahr. Das war mein Fehler 
ganz am Anfang :)

von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

Rolf M. schrieb:
> @Maxim: Korrigiere mich, wenn ich hier Blödsinn erzähle.

Alles richtig gesagt.

"Historische", oder besser gesagt, nicht gleichschwebende Stimmungen 
hört man am besten in der Musik von Bach und früher. Dann klingt die 
Musik anders. Für Romantik und später reicht gleichschwebende Stimmung.

Hier sind zwei Sachen wichtig:
1. alle historische Stimmungen haben als Grund eine Verbesserung von 
gebräuchlichen Tonarten auf Kosten von weniger gebräuchlichen. Bei 
verschiedenen Stimmungen ist das unterschiedlich erreicht. Ich selber 
mag Stimmungen "Neidhardt kleine Stadt" für Pachelbel und von Valotti 
für Bach.
2. Orgelpfeifen ziehen sich zueinander. Besonders wenn sie nebeneinander 
stehen, was auch bei Terzanordnung von Pfeifen vor allem für große 
Terzen stimmt.

Die großen Terzen von gebräuchlichen Tonarten sind schon wegen der 
Stimmung sauberer, und durch Aneinanderziehen erscheinen sie praktisch 
rein. Schöne reine große Terzen bestimmen Schönheit von Akkorden. Auch 
in Quinten ist Effekt gut hörbar. Die Quinten, die nicht schweben, die 
reinen, die klingen völlig anders.

Bei Klavier ist noch interessanter...
Die Stimmung verwendet man zwar gleichschwebende... Aber die Saiten aus 
Stahl sind hart. Das führt dazu, daß die Obertöne höher werden, als 
theoretischen, und zwar in quadratischer Abhängigkeit von Obertonnummer. 
Da wir aber musikalischen Intervalle dank Obertönen hören, klingt für 
unser Gehör eine reine Oktave zu eng, ebenso Quarten, Quinten und 
Terzen. Je kürzer sind die Saiten, um so hörbarer ist Effekt, deshalb 
ist das für jedes Modell und sogar für jedes Klavier etwas anders. 
Gerade deshalb gibt eine Stimmung nach Gehör bessere Ergebnis, als nach 
Stimmgerät - nur TLA hat hier etwas verbessert.

Die Geräte von diesen Ingenieurbüro kenne ich seit vielen Jahren. Das 
ist eine Sache für Kenner. Die haben auch billigere Modelle, für ein 
paar Hundert Euro, die keine Klavieranalyse machen können. Die 
billigsten können auch keine eigene Stimmungen speichern und können nur 
vom Werk eingestellte Stimmungen verwenden. Richtig gute kosten aber 
über Tausend. Die haben auch eine sehr interessante für Orgel 
Möglichkeit, Tonhöhe nach Raumtemperatur automatisch zu korrigieren - 
das ist aktuell, wenn man z.B. ein Orgelpositiv in einem Saal in der 
Pause stimmt, wo wegen Menschen Raumtemperatur nicht konstant bleibt.

Deshalb die Notwendigkeit, bei Stimmgeräten sehr genau in 
Centbruchteilen hören.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wie soll die Frequenz denn gemessen werden?

von Maxim B. (max182)


Lesenswert?

Johann L. schrieb:
> Wie soll die Frequenz denn gemessen werden?

Wie auch immer. Temporäres Tor.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.