Forum: Mikrocontroller und Digitale Elektronik Konvertierung von double in integer


von Felix E. (felix1601)


Lesenswert?

Hallo,

ich denke mein Anliegen ist klar, ich habe leider bis jetzt nichts im 
www gefunden, vielleicht kann mir hier jemand helfen?

von Irgendwer (Gast)


Lesenswert?

In welcher Programiersprache?
Einfach abschneiden oder genau gerundet?

double x = 12343.456;
int x = (int)y;

von Felix E. (felix1601)


Lesenswert?

Irgendwer schrieb:
> In welcher Programiersprache?
> Einfach abschneiden oder genau gerundet?
>
> double x = 12343.456;
> int x = (int)y;

Programmiere einen ESP8266 also arduino basiert
Sollte genau gerundet sein!
Geht das mit der Funktion so einfach?

das y sollte ein x sein oder?

: Bearbeitet durch User
von Axel S. (a-za-z0-9)


Lesenswert?

Felix E. schrieb:
> ich denke mein Anliegen ist klar, ich habe leider bis jetzt nichts im
> www gefunden

Dann kannst du das (das Suchen) also auch nicht?

floor(), trunc() oder round() aus der mathlib tun das. Je nachdem 
welches Verhalten du genau möchtest.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Felix E. schrieb:
> Programmiere einen ESP8266 also arduino basiert

"Also"? Den könnte man auch mit irgendwas anderem programmieren.

Wie auch immer, es geht also um C++.


> Sollte genau gerundet sein!

Dann vor dem Typecast 0.5 addieren.

Der Typecast schneidet ab.
1
double x = 1234.56;
2
3
int y = x;
4
5
int z = x  + 0.5;
6
7
printf("y = %d  z = %d\n", y, z);

Resultat:

y = 1234  z = 1235

von Markus F. (mfro)


Lesenswert?

So rundet da nix, da wird bloß abgeschnitten.

So geht's richtig:
1
    double x;
2
3
    int a = (x > 0.0 ? (int) (x + 0.5) : (int) (x - 0.5));

von Dirk B. (dirkb2)


Lesenswert?


von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Markus hat natürlich den Nagel auf den Kopf getroffen - "mein" 
Rundungsansatz versagt bei negativen Zahlen.

von Felix E. (felix1601)


Lesenswert?

Markus F. schrieb:
> So rundet da nix, da wird bloß abgeschnitten.
>
> So geht's richtig:
>
>
1
>     double x;
2
> 
3
>     int a = (x > 0.0 ? (int) (x + 0.5) : (int) (x - 0.5));
4
>

Dankeschön!

Auch für alle anderen Antworten!

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Markus F. schrieb:
> So rundet da nix, da wird bloß abgeschnitten.
>
> So geht's richtig:
>
>
1
>     double x;
2
> 
3
>     int a = (x > 0.0 ? (int) (x + 0.5) : (int) (x - 0.5));
4
>

Wofür der explizite Typecast auf int?
1
 int a = (x > 0.0 ? (x + 0.5) : (x - 0.5));

Funktioniert genausogut.

von W.S. (Gast)


Lesenswert?

Felix E. schrieb:
> ich denke mein Anliegen ist klar,

Nein, dein Anliegen ist durchaus nicht klar. Wozu ein double bemühen, 
wenn man's anschließend auf einen int herunterbrechen will?

Also, wenn man PI so rundet, dann fällt man weit hinter die alten 
Ägypter zurück, die konnten das schon besser als nur 3.

Und was wird aus 1.735E37 werden?

Also, erstmal glaube ich nicht, daß man für solche Feld-Wald-Wiese 
ausgerechnet double braucht, das rechnet sowieso kaum ein billiger µC in 
Hardware (ob der ESP8266 das etwa in HW kann?) und zweitens wäre dann 
allenfalls ein int64 oder notfalls ein long angesagt.

Besser für Meßzwecke wäre es allerdings, einfach float als single zu 
nehmen und dann auch in float zu bleiben.

Also: wozu soll's denn gut sein?

W.S.

von Sebastian S. (amateur)


Lesenswert?

Eine sehr interessante Formulierung;)

>Sollte genau gerundet sein!

von Axel S. (a-za-z0-9)


Lesenswert?

Markus F. schrieb:
> So rundet da nix, da wird bloß abgeschnitten.
>
> So geht's richtig:
>
>
1
>     double x;
2
> 
3
>     int a = (x > 0.0 ? (int) (x + 0.5) : (int) (x - 0.5));
4
>

Gibt es einen tieferen Grund, warum hier alle das Rad neu erfinden? Die 
Funktion round() aus der libm existiert, ist standardisiert und tut 
exakt das verlangte. Im Zweifelsfall ist sie auch effizienter als 
jedes Eigengewächs.

von Felix E. (felix1601)


Lesenswert?

W.S. schrieb:
> Also: wozu soll's denn gut sein?

Daten eines MPU6050 werden erfasst und umgerechnet auf grad bzw. auch 
ein komplementärfilter verwendet um das driften zu minimieren. Nun 
möchte ich die entgültigen beschleunigungsdaten in int umwandeln um sie 
danach über mqtt zu publishen, und eben die kommastellen beim empfänger 
nicht mehr benötige und das dann nur unnötig genaue daten wären, jedoch 
brauche ich für die berechnungen die kommastellen um das ergebnis so 
genau wie möglich zu halten

von Yalu X. (yalu) (Moderator)


Lesenswert?

Axel S. schrieb:
> Gibt es einen tieferen Grund, warum hier alle das Rad neu erfinden? Die
> Funktion round() aus der libm existiert, ist standardisiert und tut
> exakt das verlangte.

Ich verstehe auch nicht, warum deine beiden Beiträge (und anfangs auch
Dirks Beitrag) abgewertet worden sind. Noch besser als round ist in
diesem Fall nur lround, da dieses die Konvertierung nach long bzw. int
(was auf dem ESP8266 dasselbe ist) bereits integriert hat, was die
Funktion evtl. noch etwas schneller macht.

Also:

1
  a = lround(x);

von Axel S. (a-za-z0-9)


Lesenswert?

Yalu X. schrieb:
> Axel S. schrieb:
>> Gibt es einen tieferen Grund, warum hier alle das Rad neu erfinden? Die
>> Funktion round() aus der libm existiert, ist standardisiert und tut
>> exakt das verlangte.
>
> Ich verstehe auch nicht, warum deine beiden Beiträge (und anfangs auch
> Dirks Beitrag) abgewertet worden sind.

Haha. Dirk habe ich wieder auf 0 hoch gevotet.

Sind wohl zuviele Kasper mit Accounts (und deswegen dem Recht zu voten) 
unterwegs. Wenn ich daran denke daß das womöglich die Menschen sind die 
übernehmen, wenn ich mal in Rente gehe, dann wird mir ganz anders.

von Markus F. (mfro)


Lesenswert?

Axel S. schrieb:
> Gibt es einen tieferen Grund, warum hier alle das Rad neu erfinden? Die
> Funktion round() aus der libm existiert, ist standardisiert und tut
> exakt das verlangte.

Natürlich kann man auch round() verwenden. Und sollte das auch tun, wenn 
man sowieso die libm einbinden muß.

Wenn ich aber nur eine einzige Zeile brauche, um ganz ohne Library klar 
und verständlich hinzuschreiben, was ich will, dann spare ich mir das. 
Der Compiler kann (ohne LTO-"Tricks") inlinen und im besten Fall spare 
ich einen Funktionsaufruf.

Kann jeder halten, wie er will. Jetzt weiß der TO hoffentlich 
wenigstens, was round() tut.

von Dr. Sommer (Gast)


Lesenswert?

Markus F. schrieb:
> klar und verständlich hinzuschreiben, was ich will, dann spare ich mir
> das.

Du findest also so eine Formel verständlicher als "round"? Jeder 
Programmierer, der round sieht, weiß sofort was gemeint ist. Eine Formel 
zu entschlüsseln dauert auf jeden Fall länger.

von H.Joachim S. (crazyhorse)


Lesenswert?

Yalu X. schrieb:
> Ich verstehe auch nicht, warum deine beiden Beiträge (und anfangs auch
> Dirks Beitrag) abgewertet worden sind.

Vielleicht weil die ganze "Bewerterei" von Hause aus Nonsens ist? Sie 
hat oft nur wenig mit der fachlichen Qualität zu tun, sondern ist ein 
Spielplatz für persönliche Befindlichkeiten oder kleine Rachegelüste.

von Markus F. (mfro)


Lesenswert?

Dr. Sommer schrieb:
> Du findest also so eine Formel verständlicher als "round"? Jeder
> Programmierer, der round sieht, weiß sofort was gemeint ist. Eine Formel
> zu entschlüsseln dauert auf jeden Fall länger.

Wenn's dir gut tut, hast Du recht.

Darüber auch nur eine Minute länger nachzudenken ist m.E. Verschwendung 
von kostbarer Lebenszeit.

von Dr. Sommer (Gast)


Lesenswert?

Aha... der Aufwand für den Funktionsaufruf dürfte sowieso klein sein 
gegenüber dem für die Rundung selbst.

von A. S. (Gast)


Lesenswert?

Round liefert keinen Integer zurück.

Und dann muss man erstmal recherchieren, ob man wirklich sicher sein 
kann, dass die Konvertierung danach klappt.

von Dr. Sommer (Gast)


Lesenswert?

0.5 addieren/subtrahieren und nach int casten kann genau so gut einen 
Over/Under-Flow produzieren.

von Axel S. (a-za-z0-9)


Lesenswert?

Markus F. schrieb:
> Axel S. schrieb:
>> Gibt es einen tieferen Grund, warum hier alle das Rad neu erfinden? Die
>> Funktion round() aus der libm existiert, ist standardisiert und tut
>> exakt das verlangte.
>
> Natürlich kann man auch round() verwenden. Und sollte das auch tun, wenn
> man sowieso die libm einbinden muß.

Warum diese Einschränkung? Gibt es Geld zurück für die Nichtverwendung 
von Bibliotheksfunktionen?

Zum zweiten Punkt hat Dr. Sommer sich ja schon geäußert:

Dr. Sommer schrieb:
> Markus F. schrieb:
>> klar und verständlich hinzuschreiben, was ich will, dann spare ich mir
>> das.
>
> Du findest also so eine Formel verständlicher als "round"? Jeder
> Programmierer, der round sieht, weiß sofort was gemeint ist. Eine Formel
> zu entschlüsseln dauert auf jeden Fall länger.

Wahrscheinlich stopft er das dann selber in eine Funktion und nennt sie 
my_round() (weil nur round() geht ja nicht, da könnte es zu Konflikten 
kommen, falls libm für was anderes dazugelinkt wird)

von Yalu X. (yalu) (Moderator)


Lesenswert?

Markus F. schrieb:
> Wenn ich aber nur eine einzige Zeile brauche, um ganz ohne Library klar
> und verständlich hinzuschreiben, was ich will, dann spare ich mir das.
> Der Compiler kann (ohne LTO-"Tricks") inlinen und im besten Fall spare
> ich einen Funktionsaufruf.

Auf einem Prozessor ohne FPU wie dem ESP8266 benötigt

1
(int)(x>0.0 ? x+0.5 : x-0.5)

3 direkte Funktionsaufrufe (Vergleich, Addition/Subtraktion und Cast),

1
(int)round(x)

2 direkte Funktionsaufrufe (round und Cast) und

1
lround(x)

1 direkten Funktionsaufruf (lround).

Es sind aber nicht nur die Funktionsaufrufe selbst, an denen Zeit
gespart werden kann. Man kann davon ausgehen, dass die aufgerufenen
FP-Funktionen intern auf Assembler-Ebene sehr gut auf ihre jeweilige
Aufgabe hin optimiert sind. Je spezifischer diese Aufgabe ist, umso
besser ist i.Allg. auch die Optimierung. So muss bspw. in round nicht
nach positivem oder negativen Vorzeichen unterschieden werden, da in der
internen Darstellung die FP-Zahl bereits getrennt nach Betrag und
Vorzeichen vorliegt. In lround muss auch nicht explizit nach int bzw.
long gecastet werden, da das in einem Aufwasch mit der Bestimmung des
ganzzahligen Anteils erfolgen kann.

Somit dürfte die zweite Variante deutlich schneller als die erste und
die dritte deutlich schneller als die zweite sein.

Vielleicht hat ja jemand Lust, die Laufzeiten der drei Varianten auf
einem ESP8266 zu messen.

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.