C wie mit großen Zahlen rechnen

Dshing

Lt. Commander
Registriert
Nov. 2007
Beiträge
1.436
Hi, ich hab vergessen wie man mit großen Zahlen rechnet.
Ich will folgende Zahl berechnen(ohne Nachkommastellen)

a=(9085466*1315097036/2097152-2420281617)/32768;

mit int64_t und double kommt immer ein Überlauf zustande.

Es sollte 100009 raus kommen.
 
Du rechnest mit ints, wenn du longs willst must du LL hinter jede Zahl schreiben damits als long long literal erkannt wird, z.B. 123LL.
Für double muss die Zahl mit .0 ändern.

PS: Da kommt aber sowieso was anderes raus.
 
Wo ist da jetzt das Problem? Es wurde doch bereits alles gesagt.
Code:
int64_t a = (9085466ll*1315097036/2097152-2420281617ll)/32768;
Du kannst a auch vom Typ int wählen. Nur die Berechnung muss im long long Wertebereich sein.
 
Zuletzt bearbeitet:
Also konkret geht es um folgenden Code:

Code:
int64_t DRUCK ()
{
		int64_t SENS=40127;
		int64_t OFF=36924;
		int64_t TCS=23317;
		int64_t TCO=23282;
		int64_t TREF=33464;
		int64_t TEMPSENS=28312;
		int64_t temperature;
		int64_t dT;
		int64_t TEMP;
		int64_t Offset;
		int64_t Sensitivity;
		int64_t pressure;
		int64_t P;
		int8_t part1a=130;
		int8_t part2a=193;
		int8_t part3a=62;
		int8_t part1b=138;
		int8_t part2b=162;
		int8_t part3b=26;

		temperature=(part1a<<16)+(part2a<<8)+part3a;
		dT=temperature-TREF*256LL;
		TEMP=2000LL+dT*TEMPSENS/8388608LL;
		Offset=OFF*65536LL+(TCO*dT)/128LL;
		Sensitivity=SENS*32768LL+(TCS*dT)/256LL;
		pressure=(part1b<<16)+(part2b<<8)+part3b;
		P=(pressure*Sensitivity/2097152LL-Offset)/32768LL;
		return P;}

Hier müsste die 100009 zurückgegeben werden, aber das tut es bei mir nicht, sonder bei mir kommt 0xFFFF98E8 raus.
 
Sagt dir dein Compiler denn gar nichts? Also der MSVC++ Compiler spuckt bei mir "warning C4309: 'initializing' : truncation of constant value" für die Zeilen 16, 17, 19 und 20 aus. Das ist auch dein Problem. Schau dir diese Zeilen noch einmal genau an, dann sollte dir auffallen was nicht passt.

Gruß
BlackMark
 
Problem hier ist: deine int8_t-Shifts laufen über. Wenn das gefix ist, sollte es eigentlich tun.
 
Naja, die Shifts sind eigentlich nicht das Problem, sondern die Initialisierung. In ein (signed) int8 passen nur Zahlen von -128 bis +127, deswegen läuft die Variable schon bei der Initialisierung über.

Gruß
BlackMark
 
Es passen die Zahlen von 0000 0000 bis 1111 1111, ganz normale, ne :D
 
Hmm, also egal ob ich uint8_t oder int8_t mache das Ergebnis bleibt 0xFFFF98E8 :freak:
Hab das Grade mal bei MS Visualstudio versucht, da funktioniert es.
Aber auf meinem µC(ATmega168) will es nicht laufen. Ich nutze das AVR Studio zum programmieren. Was ist da los? Das ist beides C und die gleichen Bibliotheken.
 
@F_GXdx: Binär angeschrieben, natürlich. Nur, dass alles ab 1000 0000 als negative Zahl interpretiert wird. Alle darauf folgenden Berechnungen wären deshalb falsch. "int8_t part1a=130;" wird zum Beispiel zu "int8_t part1a=-126;", nicht gerade das was man haben möchte, auch wenn Binär in beiden Fällen 1000 0010 in der Variable steht.

@Dshing: Kann nicht für den AVR Studio Compiler sprechen, aber eigentlich sollte es mit einem unsigned int8 funktionieren. Falls nicht kannst du ja auch ein int16 daraus machen, dann muss es auf jeden Fall gehen.

Edit: Ich vermute es funktioniert nicht, weil bei zB "(part1a<<16)" 16 nicht als int32 angesehen wird, wie es beim MSVC++ Compiler der Fall wäre. Müsstest du jedoch testen, ist nur eine Vermutung.

Edit2: Achso, falls meine Vermutung stimmt, dann wird int16 auch nicht ausreichen, dann müsstest du int32 aus deinen int8 Variablen machen, oder du castest 16 nach int32: "(part1a<<(int32_t)16)" und "uint8_t part1a=130;"

Gruß
BlackMark
 
Zuletzt bearbeitet:
Des hoaßt ned schift sondern shift :D
 
Zurück
Oben