Go Down

Topic: Double Modulo (Read 1 time) previous topic - next topic

stock95

Hallo erstmals

und zwar ich bekomme jedesmal diese Fehlermeldung :

error: invalid operands of types 'double' and 'int' to binary 'operator%'

wenn ich versuche mit einer Double Zahl Modulo berechne.


Hier ist ein Beispielcode:


Code: [Select]
double x = 100000;
int y = 3;
int s = 0;

void setup(){
  Serial.begin(9600);
 
}


void loop(){
 
s = x % y;
Serial.println(s);
 
 
 
}


x muss eine Double Zahl bleiben

pylon

Modulo ist der Rest einer Ganzzahlen-Division. Die Operation ist auf Gleitkommazahlen nicht definiert, weil dort eine Division immer durchgeführt werden kann (Ausnahme: 0) und keinen Rest übrig lässt. Wenn Du mit Ganzzahlen rechnen willst, solltest Du auch Ganzzahlen als Typ verwenden, also Integer (in welcher Ausprägung auch immer).

Was willst Du genau erreichen? Wieso muss x ein double sein?

stock95

Da x sonst eine Variable ist und zum Teil die Zahl größer ist als Integer zulässt

jurs

#3
Nov 27, 2012, 11:27 am Last Edit: Nov 27, 2012, 11:55 am by jurs Reason: 1

x muss eine Double Zahl bleiben


Und die Modulo-Operation ist nur für Ganzzahlenwerte definiert.

Z.B.:
s = round(x) % y;


Da x sonst eine Variable ist und zum Teil die Zahl größer ist als Integer zulässt


Ganzzahl-Datentypen größer als int existieren.

Die Typen "long" http://arduino.cc/en/Reference/Long
und "unsigned long" http://arduino.cc/en/Reference/UnsignedLong
stehen sogar in der Arduino-Dokumentation drin.

Tatsächlich kannst Du sogar 64-Bit Integers vom Typ "long long" verwenden, damit sind sogar Zahlen bis hoch zu 9.223.372.036.854.775.807, also mit 19 signifikanten Dezimalstellen, bis auf die letzte Stelle genau darstellbar.

pylon

Quote
Da x sonst eine Variable ist und zum Teil die Zahl größer ist als Integer zulässt


Wenn die Zahl grösser als 24bit wird (ca. 16Mio), wird sie in einem double (ist auf dem Arduino gleich float und somit 32bit) nicht mehr genau dargestellt, sondern nur angenähert und somit ist das Resultat einer Modulo-Operation sowieso nicht sicher korrekt. Und Zahlen bis 32bit kannst Du mit einem unsigned long noch als Integer darstellen, wie Dimivo bereits ausführte.

uwefed


Tatsächlich kannst Du sogar 64-Bit Integers vom Typ "long long" verwenden, damit sind sogar Zahlen bis hoch zu 9.223.372.036.854.775.807, also mit 19 signifikanten Dezimalstellen, bis auf die letzte Stelle genau darstellbar.

Dieses Dateiformat gibt es aber in der Arduino Programmierumgebung nicht.
Grüße Uwe

jurs

#6
Nov 27, 2012, 02:10 pm Last Edit: Nov 27, 2012, 02:27 pm by jurs Reason: 1

Dieses Dateiformat gibt es aber in der Arduino Programmierumgebung nicht.


Welche Uralt-Version der Arduino Programmierumgebung meinst Du?

Aktuelle Versionen haben selbstverständlich den Datentyp "long long" drin und können damit umgehen.

Das einzige was bei Arduiono fehlt, aber das ist bei anderen AVR-GCC Programmierumgebungen genau dasselbe, ist eine Möglichkeit, um LongLong-Variablen in einen String umzuwandeln. Z.B. wenn man die Zahl in voller Länge ausgeben möchte. Also um einen "long long" 64-bit Integerwert in einen String umzuwandeln, da ist man auf sich selbst gestellt.

Schwierig ist das allerdings auch nicht. Einen Sketch mit einer selbst implementierten "longlong2char" (funktioniert in der Form aber nur für positive Zahlen) Funktion hänge ich mal dran.

Code: [Select]

void setup(){
 Serial.begin(9600);
}


void longlong2char(char *buf,byte buflen,long long number)
{
byte count=0;
memset (buf,0,buflen);
while (number>10)
{
  buf[count]=(number % 10) +'0';
  number= number / 10;
  count++;
}
buf[count]=number+'0';
strrev(buf);
}

long long x = 9223372000000000000LL;
char longstrbuf[20];

void loop()
{
x++;
longlong2char(longstrbuf,sizeof(longstrbuf),x);
Serial.println(longstrbuf);
delay(1000);
}


Es würde mich wirklich wundern, wenn jemand noch eine Uralt-Arduino Umgebung hat, die "long long" 64-Bit Ganzzahlen nicht kompiliert.


mkl0815

Hmm, stimmt.
Code: [Select]
void setup() {
long long x=0LL;
Serial.begin(9600);
Serial.println(sizeof(x));
 
}

void loop() {}

Das liefert den WErt "8", also 64bit. Wusste ich aber bisher auch nicht. Leider wird der Datentyp in der Referenz nicht erwähnt und ich vermute, das wird intern per Software abgebildet, wir float auch. Aber gut zu wissen.

jurs


Das liefert den WErt "8", also 64bit. Wusste ich aber bisher auch nicht. Leider wird der Datentyp in der Referenz nicht erwähnt und ich vermute, das wird intern per Software abgebildet, wir float auch. Aber gut zu wissen.


Ja natürlich in Software.
So wie bei allen Nicht-8-Bit-Datentypen auf einem 8-Bit-Controller.

Und die Programme werden ganz schön groß, wenn man diese 64-Bit Datentypen in seinem Programm verwendet und damit rechnet, da kommt ein ganz ordentlicher Fußabdruck an Datencode zusammen.

Übrigens ist in meiner oben geposteten Konvertierungsroutine von "long long" in "char array" noch ein herber Fehler drin, die Abbruchbedingung in der while-Schleife stimmt nicht.

Statt (fehlerhaft):
while (number>10)
Setze (korrigiert):
while (number>=10)

Wer auch eine Routine zum Formatieren von "langen negativen Zahlen" benötigt und Probleme beim Coden des Minuszeichens hat, ggf. einfach fragen, dann poste ich noch was dazu.

Fat D

Streng genommen hat die Standard-C-Mathematikbibliothek eine Modulo-Funktion für floating point Zahlen, aber nicht über den %-Operator, sondern mit der fmod(double,double)-Funktion. Wie gut sie von avr-libc und Arduino implementiert ist weiß ich jedoch nicht. Aber selbst wenn, bleibt das bereits von anderen erwähnte Problem der Präzision von floating point.

stock95

danke mit long funktioniert es.

Go Up