konvertieren von float-zu kurz-mit minimalem Verlust an Genauigkeit
Habe ich diese Sinus-Welle, die erzeugt floating-point-Werte (z.B. 0.37885), aber ich will Sie als shorts. Direkte Umwandlung mit kurzen gibt mir einen Wert von 0. also, was ist die Lösung?
Kann mir jemand sagen, wie es zu tun - idealerweise ohne Verlust der Genauigkeit - oder minimalem Verlust an Genauigkeit, wenn das ist alles, was möglich ist?
- Die Größe der
float
ist in der Regel 4 bytes, und die Größe dershort
ist in der Regel 2 bytes. Wie genau sind Sie in der Hoffnung zu vermeiden, Verlust an Präzision bei der Quetschung 4 Daten-bytes in 2 bytes an Daten? - Zu helfen, zu verstehen, das problem, das Sie versuchen zu lösen, können Sie erklären, warum Sie benötigen, um zu speichern ein Schwimmer in einem kurzen?
- Plus, wie werden Sie zu "konvertieren" ein floating-point-Wert auf eine nicht-floating-point?
- Sie müssen entscheiden, entweder einen bestimmten Punkt, um für das niedrigste bit, oder schreiben Sie code zum speichern der
float
wie die FPU normalerweise tut. - Das ist nicht ein Problem. Wenn Sie eine ganze Zahl, die gleiche Größe (
int
tun würde, auf den meisten Plattformen), dann gibt es kein problem mit Hinblick auf die Art der Daten. Zum Beispiel, gegebenfloat f
undint i
Sie tun könneni = *(int*)&f
. - Unmöglich. Alles, was Sie bekommen, ist gleich null. Die Frage macht keinen Sinn.
- Ich meinte, wie kann man speichern
0.37885
in einer Art, die nicht dezimale zahlen? Alles, was Sie bekommen, ist0
... Macht es Sinn? - Verwenden
i = *(int*)&f
, und zu einem späteren Zeitpunkt verwendenf = *(float*)&i
. Die variablef
behält seinen ursprünglichen Wert. - Ich verstehe, dass es sein Verlust. Ich habe das Sinus-Welle, die Werte generiert wie oben erwähnt, aber ich möchte, dass Sie als shorts. Direkte Umwandlung mit kurzen gibt mir einen Wert von 0. also, was ist die Lösung?
- Hast du vergessen, dass dies ist java?
- float hat 23 bit Mantisse, wie können Sie fit, dass in 16 bit, noch nicht einmal eingerechnet die zusätzliche Reichweite durch 8 bits von exponent
- Nein, ich war unvorsichtig genug, nicht zu bemerken, dass, unter der Annahme, dass die Frage markiert, wie C (und Sie wissen, was Sie sagen, über die Mutterschaft der Annahmen)...
- Sinus nimmt Werte im Bereich [-1,1]. Es gibt nur drei Werte in diesem Bereich, der dargestellt werden kann in jeder integer-Typ, -1, 0, und 1.
- Ich nehme an, Sie haben Werte zwischen -1 und 1 haben will, kurze Ganzzahlen, um daraus eine wave-Datei oder geben Sie Sie in einen sound-Treiber. In diesem Fall einfach tun:
intvalue = floatvalue * 65536.0f - 32768.0f;
. Möglicherweise müssen code hinzufügen, schneiden Sie überschüssige. - Danke für die info. Ich bin es nun darum, Sie so Kurz.MaxValue für die android-hörgeschichte sound-Funktionalität, wie es akzeptiert eine kurze Puffer für die audio-Wiedergabe.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Verlieren Sie den gebrochenen Teil:
Edit:
Vielleicht wollten Sie wissen, wie Sie die bits einer float (4 bytes) in eine int (4 bytes):
(http://docs.oracle.com/javase/7/docs/api/java/lang/Float.html#floatToRawIntBits(float))
Im Prinzip könnte man nur multiplizieren Sie ihn mit 100000, konvertieren Sie es in int, dann subtrahieren -32,767 und konvertieren es zu kurz. Wenn das immer noch steckt Sie in den -32,767 bis 32.767 Reihe für alle Werte, das ist wahrscheinlich das beste, was Sie tun können. Ansonsten haben Sie zu beschränken, die Präzision und multipliziert mit 10000.
Und wenn Sie den kurzen, natürlich haben Sie daran zu erinnern, zu teilen es wieder nach unten.
short
ist ein integraler Typ, so kann es enthält nur ganze zahlen. Die nur zwei Möglichkeiten für0.37885
imshort
sind0
oder1
, die beide (so scheint es mir) verlieren Sie einiges an Präzision.Also die Antwort ist: Wenn Sie in Ordnung sind, verlieren alle Bruchzahlen, verwenden Sie entweder eine Besetzung,
Float#shortValue
, oderMath.round(float)
(und Stimmen die daraus resultierendenint
zushort
).Beispiel: Live-Kopie
Ausgabe:
In einem Kommentar sagte Sie:
Ah, jetzt sind wir etwas tun können, dass. Vermutlich sind die Werte, die Sie bekommen, sind alle zwischen
0
und1
. Sie können speichern Sie Sie als shorts durch die Multiplikation. Da das Angebot von einemshort
ist von-32.768 bis 37,767, eine bequeme Zahl zu multiplizieren, die Ihnen von vielleicht 10000:Die Zahl, die wir bekommen würde für dein Beispiel wäre
3789
. Beispiel: Live-KopieIst das nicht die gleichen Wert, natürlich, ist es das Wert multipliziert mit zehntausend, so dass überall Sie gehen, es zu benutzen, Sie müssten, um zu ermöglichen, dass.
int
tun würde, auf den meisten Plattformen), dann gibt es kein problem mit Hinblick auf die Art der Daten. Zum Beispiel, gegebenfloat f
undint i
Sie tun könneni = *(int*)&f
.&
?float
undshort
sind nicht die gleiche Größe haben, und B) Es ist sehr unwahrscheinlich, dass der OP will dieshort
(oderint
) Blick auf die bits, die aus derfloat
. 🙂int
. Sobald Sie Sie Lesen, wieder in einefloat
, es behält seine ursprüngliche (Fließkomma -) Wert.Wenn Sie Ihre Eingabe
float
Werte in einem definierten Bereich (für jetzt lassen Sie uns annehmen, Sie sind in den Bereich der-1..1
exklusive), Sie können multiplizieren Sie Sie, um einen Wert, dessen Bruchteil du wirst wegwerfen.Gültig Nahkampf ist:
-32768..32767
so können Sie mehrere mit32768
in diesem Fall (max-kurz - /max input Wert).Beispiel:
Entschlüsseln
short
Wertfloat
: