Ich implementiere einen Taschenrechner in einem Mikrocontroller, der über die serielle Schnittstelle gesteuert wird. Zum Beispiel würde ich senden 1234*5678=
und es würde mit antworten 7006652\r\n
. Ich habe den Code dafür mit dem C18-Compiler geschrieben.
Wenn ich sende 123456*789123=
, bekomme ich die Antwort 2932688576
, die falsch ist. Die richtige Antwort wäre gewesen 97421969088
, aber das läuft einem über unsigned long
.
Ich möchte das Überlauflimit nicht erhöhen, aber ich hätte gerne eine Möglichkeit zu überprüfen, ob es einen Überlauf gegeben hat. In ASM wäre das möglich, indem das entsprechende Bit im STATUS-Register überprüft wird, aber mit C würde dieses Bit gelöscht, bevor ich es lesen könnte, oder?
Am besten wäre eine allgemeine Lösung, um zu sehen, ob ein Überlauf aufgetreten ist.
Es mag Tricks in Bezug auf das STATUS-Register geben, aber der folgende generische (ungetestete) Code ist etwas, an das ich gedacht habe, um die Anzahl der Bits zu überprüfen, die zur Darstellung jedes Eingangs erforderlich sind, indem wiederholte Bitverschiebungsoperationen nach rechts durchgeführt werden, bis der Wert leer ist.
Wenn Sie dann die beiden Ergebnisse addieren, sollten Sie in der Lage sein, herauszufinden, ob die Ausgabe 32 Bit überläuft.
unsigned long a = 123456;
unsigned long b = 789123;
int calc_bit_size(unsigned long v)
{
int bit_count = 0;
while (v > 0)
{
bit_count++;
v >>= 1;
}
return bit_count;
}
if (calc_bit_size(a) + calc_bit_size(b) > 32)
printf("Overflow!")
else
printf("%lu", a * b);
Lassen Sie das interne Ergebnis einfach so breit sein wie die Summe der Breite der Operanden, und prüfen Sie dann, ob das Ergebnis nicht höher als extern zulässig war. Wenn der PIC18 einen Hardware-Multiplikator hat, ist dies nicht wirklich rechenintensiv und völlig genau, im Gegensatz zu dem Verfahren zur Bestimmung der Summe der Position der höchstwertigen Nicht-Null-Ziffer der Operanden.
Siehe Seite 174 des Dokuments in http://ptgmedia.pearsoncmg.com/images/0321335724/samplechapter/seacord_ch05.pdf
user_1818839
gbarry
Benutzer17592
gbarry