Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

int minus int

0 views
Skip to first unread message

Thomas Koenig

unread,
Nov 27, 2009, 1:40:22 AM11/27/09
to
Hallo,

angenommen, ich habe

int a, b;
unsigned int res;

Wie berechne ich am besten die Differenz von a und b und weise sie res zu?

res = a - b;

geht IMHO nicht, weil ja beispielsweise a=INT_MAX und b=-INT_MAX sein kᅵnnte.

Braucht man eine Fallunterscheidung, die die alle vier Fᅵlle

a >= 0 && b >= 0
a >= 0 && b < 0
a < 0 && b >= 0
a < 0 && b < 0

unterschieden werden, oder geht es auch eleganter?

Thomas Richter

unread,
Nov 27, 2009, 3:03:48 AM11/27/09
to
Thomas Koenig schrieb:

Frage ist eher, was Du erwartest, dass passiert? Beispielsweise, ist
denn a >= b garantiert?

Insofern "gehen" tut das obige schon, hat aber kein vom Standard
definiertes Verhalten, falls die Subtraktion ᅵberlᅵuft. Das hat aber mit
der Umwandlung nach unsigned int nichts zu tun.

Grᅵᅵe,
Thomas

Rainer Weikusat

unread,
Nov 27, 2009, 7:25:31 AM11/27/09
to
Thomas Koenig <tko...@netcologne.de> writes:
> angenommen, ich habe
>
> int a, b;
> unsigned int res;
>
> Wie berechne ich am besten die Differenz von a und b und weise sie res zu?
>
> res = a - b;
>
> geht IMHO nicht, weil ja beispielsweise a=INT_MAX und b=-INT_MAX
> sein k�nnte.

Falls das fuer Deine Eingabewerte eine Rolle spielt, musst Du auf
Bereichsueberlauf pruefen, dh

if ((a == INT_MAX && b == -INT_MAX)
|| (a == -INT_MAX && b == INT_MAX))
fputs("Sie verlassen den amerikanischen Sektor!\n", stderr);
else res = a - b;

Message has been deleted

Rainer Weikusat

unread,
Nov 27, 2009, 9:32:46 AM11/27/09
to
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> Thomas Koenig <tko...@netcologne.de> writes:
>>Wie berechne ich am besten die Differenz von a und b und weise sie res zu?
>
> Ich habe einmal etwas �hnliches f�r Java geschrieben.
> Es erm�glicht die Berechnung des Mittelwertes zweier
> ganzer Zahlen:
>
> public int intFloorMiddle()
> { /* Based on code by Peter Luschny. */
> final int result;
> result =
> ( ( this.number0 >> 1 )+( this.number1 >> 1 )+
> ( this.number0 & this.number1 & 1 ));
> return result; }

[...]

> Allerdings macht er davon Gebrauch, da� in Java die bin�re
> Darstellung von int-Zahlen wohl genauer spezifiziert ist als
> in C. Wenn Du jetzt solche �Bit-Tricks� f�r eine
> Zweierkomplementdarstellung in C schriebest, dann w�ren sie
> f�r eine Einerkomplementdarstellung m�glicherweise nicht
> mehr g�ltig

Das Ergebnis ist allgemein 'implementation defined' (6.5.7|5).

Message has been deleted

Markus Wichmann

unread,
Nov 27, 2009, 3:43:29 PM11/27/09
to
Thomas Koenig (tko...@netcologne.de) schrieb:

> Hallo,
>
> angenommen, ich habe
>
> int a, b;
> unsigned int res;
>
> Wie berechne ich am besten die Differenz von a und b und weise sie res zu?
>
> res = a - b;
>
> geht IMHO nicht, weil ja beispielsweise a=INT_MAX und b=-INT_MAX sein könnte.
>
> Braucht man eine Fallunterscheidung, die die alle vier Fälle
>
> a >= 0 && b >= 0
> a >= 0 && b < 0
> a < 0 && b >= 0
> a < 0 && b < 0
>
> unterschieden werden, oder geht es auch eleganter?

Was möchtest du denn haben? Den Abstand zwischen a und b?

if (a >= b)


res = a - b;

else
res = b - a;

Oder Subtraktion mit "Saturation", d.h.

if (a >= b)


res = a - b;

else
res = 0;

oder was?

Tschö,
Markus
--
Nur weil ein Genie nix reißt, muß ja nun nicht gleich jeder Idiot
pausieren... Bully hats ja auch geschafft.
-- gUnter nanonüm in de.alt.anime

Michael Schumacher

unread,
Nov 28, 2009, 2:49:55 AM11/28/09
to
Thomas Koenig wrote:

> angenommen, ich habe
>
> int a, b;
> unsigned int res;
>
> Wie berechne ich am besten die Differenz von a und b und weise sie res zu?
>
> res = a - b;
>
> geht IMHO nicht, weil ja beispielsweise a=INT_MAX und b=-INT_MAX sein

> könnte.

Ich sehe nicht wirklich, was der o.g. Code praktisch bezwecken soll,
bzw. wie er überhaupt sinnvoll eingesetzt werden könnte. Warum soll
die Differenz zweier beliebiger ints per unsigned dargestellt werden
(res ist ja immer >= 0, selbst wenn b > a ist!)?

In allen Fällen /genau/ kann man's offensichtlich nur per long (long)
berechnen (also einem skalaren Typ "> sizeof(int)"; wg. -2 * INT_MAX),
ansonsten scheint mit nur Saturierung gegen Null oder irgendein "MAX"
einen Sinn zu machen.


mike

Thomas Koenig

unread,
Nov 30, 2009, 3:14:00 PM11/30/09
to

Thomas Koenig

unread,
Nov 30, 2009, 3:25:18 PM11/30/09
to
On 2009-11-28, Michael Schumacher <mi...@gmx.de> wrote:

> Ich sehe nicht wirklich, was der o.g. Code praktisch bezwecken soll,

> bzw. wie er ᅵberhaupt sinnvoll eingesetzt werden kᅵnnte. Warum soll


> die Differenz zweier beliebiger ints per unsigned dargestellt werden
> (res ist ja immer >= 0, selbst wenn b > a ist!)?

Ich wᅵrde halt mal gerne eine Mᅵglichkeit kennen, die Differenz
zweier Ints ausrechnen, wobei die ints den vollen Bereich der Zahlen
ausnutzen sollen kᅵnnen. Das Vorzeichen mᅵsste ich natᅵrlich noch
gesondert betrachten.

> In allen Fᅵllen /genau/ kann man's offensichtlich nur per long (long)


> berechnen (also einem skalaren Typ "> sizeof(int)"; wg. -2 * INT_MAX),

Die Existenz eines Integer-Typs mit grᅵᅵerem Wertebereich als int ist
nicht durch die Norm garantiert, AFAICR.

Oder kann man sowas wie die Differenz zweier ints ausrechnen gar nicht
in normgerechtem C?

Claus Reibenstein

unread,
Nov 30, 2009, 4:53:05 PM11/30/09
to
Thomas Koenig schrieb:

> Oder kann man sowas wie die Differenz zweier ints ausrechnen gar nicht
> in normgerechtem C?

Du kannst bei _allen_ numerischen Operationen Ergebnsse erhalten, die im
gewᅵhlten Zahlenformat nicht mehr darstellbar sind (diesen Effekt nennt
man Overflow), und das nicht nur C, sondern in _jeder_
Programmiersprache. Es liegt in der Verantwortung des Programmierers,
solche Fᅵlle zu erkennen und zu behandeln.

Gruᅵ. Claus

Message has been deleted
Message has been deleted

Thomas Koenig

unread,
Dec 1, 2009, 2:00:51 AM12/1/09
to
On 2009-11-30, Claus Reibenstein <4spame...@kabelmail.de> wrote:
> Thomas Koenig schrieb:
>
>> Oder kann man sowas wie die Differenz zweier ints ausrechnen gar nicht
>> in normgerechtem C?
>
> Du kannst bei _allen_ numerischen Operationen Ergebnsse erhalten, die im
> gewᅵhlten Zahlenformat nicht mehr darstellbar sind (diesen Effekt nennt
> man Overflow), und das nicht nur C, sondern in _jeder_
> Programmiersprache.

Naja, es gibt ja auch die Mᅵglichkeit, Zahlen beliebiger Grᅵᅵe
darzustellen (z.B. mit gmp).

> Es liegt in der Verantwortung des Programmierers,
> solche Fᅵlle zu erkennen und zu behandeln.

Genau, und meine Frage war, wie man das am besten macht, am relativ
einfachen Beispiel der Subtraktion zweier int-Zahlen, und zwar nach
den Regeln der C-Norm, ohne sich (z.B.) auf Zweierkomplement zu
verlassen.

Multiplikation dᅵrfte noch ein bisschen schwieriger sein.

Claus Reibenstein

unread,
Dec 1, 2009, 2:35:49 AM12/1/09
to
Thomas Koenig schrieb:

> On 2009-11-30, Claus Reibenstein <4spame...@kabelmail.de> wrote:
>
>> Du kannst bei _allen_ numerischen Operationen Ergebnsse erhalten, die im
>> gewᅵhlten Zahlenformat nicht mehr darstellbar sind (diesen Effekt nennt
>> man Overflow), und das nicht nur C, sondern in _jeder_
>> Programmiersprache.
>
> Naja, es gibt ja auch die Mᅵglichkeit, Zahlen beliebiger Grᅵᅵe
> darzustellen (z.B. mit gmp).

Das fᅵllt in diese Rubrik:

>> Es liegt in der Verantwortung des Programmierers,
>> solche Fᅵlle zu erkennen und zu behandeln.
>
> Genau, und meine Frage war, wie man das am besten macht, am relativ
> einfachen Beispiel der Subtraktion zweier int-Zahlen, und zwar nach
> den Regeln der C-Norm, ohne sich (z.B.) auf Zweierkomplement zu
> verlassen.

Eine Universallᅵsung gibt es nicht, auch keine "nach den Regeln der
C-Norm", da die C-Norm fᅵr solche Fᅵlle nichts vorsieht. Es hᅵngt von
der jeweiligen Situation ab, welche Werte vorkommen, ob diese zu einem
Overflow fᅵhren kᅵnnen und wie der abzufangen ist, und es hᅵngt von der
Implementierung ab, was passiert, wenn es wirklich mal zu einem Overflow
kommt.

> Multiplikation dᅵrfte noch ein bisschen schwieriger sein.

Das Problem ist im Prinzip das gleiche.

Gruᅵ. Claus

Rainer Weikusat

unread,
Dec 1, 2009, 7:23:26 AM12/1/09
to
Thomas Koenig <tko...@netcologne.de> writes:
> On 2009-11-28, Michael Schumacher <mi...@gmx.de> wrote:
>> Ich sehe nicht wirklich, was der o.g. Code praktisch bezwecken soll,
>> bzw. wie er �berhaupt sinnvoll eingesetzt werden k�nnte. Warum soll

>> die Differenz zweier beliebiger ints per unsigned dargestellt werden
>> (res ist ja immer >= 0, selbst wenn b > a ist!)?
>
> Ich w�rde halt mal gerne eine M�glichkeit kennen, die Differenz

> zweier Ints ausrechnen, wobei die ints den vollen Bereich der Zahlen
> ausnutzen sollen k�nnen. Das Vorzeichen m�sste ich nat�rlich noch
> gesondert betrachten.
>
>> In allen F�llen /genau/ kann man's offensichtlich nur per long (long)

>> berechnen (also einem skalaren Typ "> sizeof(int)"; wg. -2 * INT_MAX),
>
> Die Existenz eines Integer-Typs mit gr��erem Wertebereich als int ist

> nicht durch die Norm garantiert, AFAICR.
>
> Oder kann man sowas wie die Differenz zweier ints ausrechnen gar nicht
> in normgerechtem C?

Die von Dir zugrundegelegte 'Differenz zweier ints' gibt es in dieser
Form nicht in 'normgerechtem C': Es gibt eine Subtraktionsoperator,
der (fuer den gebenen Fall) eine Abbildung

int x int -> int

ist. Offensichtlich kann der fuer eine Berechnung, die eine Abbildung

int x int -> sonstwas

braeuchte, wobei 'sonstwas' ausser, dass es jedenfalls nicht 'int'
ist, noch nicht einmal klar definiert wurde, nicht benutzt
werden. Eine solche Berechnung kann, mangels Definiertheit, ueberhaupt
nicht durchgefuehrt werden.

Georg Bauhaus

unread,
Dec 1, 2009, 7:43:23 AM12/1/09
to
Rainer Weikusat schrieb:

> Die von Dir zugrundegelegte 'Differenz zweier ints' gibt es in dieser
> Form nicht in 'normgerechtem C': Es gibt eine Subtraktionsoperator,
> der (fuer den gebenen Fall) eine Abbildung
>
> int x int -> int
>
> ist. Offensichtlich kann der fuer eine Berechnung, die eine Abbildung
>
> int x int -> sonstwas
>
> braeuchte, wobei 'sonstwas' ausser, dass es jedenfalls nicht 'int'
> ist, noch nicht einmal klar definiert wurde, nicht benutzt
> werden. Eine solche Berechnung kann, mangels Definiertheit, ueberhaupt
> nicht durchgefuehrt werden.

Die Bezeichnung "int" d�rfte f�r diesen Datentyp von C "pragmatisch
ungenau", eigentlich: v�llig unpassend gew�hlt worden sein.
Eine historische Altlast mit wiederkehrenden Sp�tfolgen,
wie man sieht, meine ich.

Dass Programmierer das "sonstwas" in "int x int -> sonstwas" h�ufig mit
"int" gleichsetzen, und dabei nicht v�llig in die falsche Richtung
vermuten, scheint mir auch den Assoziationen geschuldet, die
C's Bezeichnung "int" und die vielen "bekannten" Operator-Symbole
hervorrufen.
Und so entsteht ein Haufen von "Fl�chtigkeits-Fehlern"...
C ist da nicht ganz allein, stellt aber im Effekt den Sachverhalt
mathnozentrischer Fehlbenennung und "wir-wissen-dass-int-kein-integer-ist,
ihr D�dels", besonders markant zur Schau.

Michael Schumacher

unread,
Dec 1, 2009, 12:39:08 PM12/1/09
to
Thomas Koenig wrote:

> On 2009-11-28, Michael Schumacher <mi...@gmx.de> wrote:
>

[Differenz zweier int-Werte]
>> In allen Fällen /genau/ kann man's offensichtlich nur per long (long)


>> berechnen (also einem skalaren Typ "> sizeof(int)"; wg. -2 * INT_MAX),
>

> Die Existenz eines Integer-Typs mit größerem Wertebereich als int ist


> nicht durch die Norm garantiert, AFAICR.
>
> Oder kann man sowas wie die Differenz zweier ints ausrechnen gar nicht
> in normgerechtem C?

Wenn die jeweilige Implementierung keinen Ganzzahlentyp > int kennt,
wird's haarig (aber nicht unmöglich: Du mußt halt einen entsprechenden
Datentyp konstruieren, dazu die Substraktion selbst programmieren, und
natürlich auch ein eigenes printf() für den neuen Datentyp schreiben).

Im "Normalfall" steht aber ein größerer Datentyp zur Verfügung (evtl.
gcc/glibc benutzen, bei dem "long long" üblicherweise > int ist), und
natürlich gibt es bei "eingebauten" Typen /immer/ Grenzen. Die sind
für gewöhnlich in der Praxis hinreichend, aber wenn es beliebig genau
werden muß, bleibt eben nur die Eigenimplementierung (s.o.) oder die
Benutzung bereits bestehender Bibliotheken, die beliebige Genauigkeit
zur Verfügung stellen, z.B. die "GNU MP Bignum Library".


mike

Thomas Koenig

unread,
Dec 2, 2009, 2:51:48 PM12/2/09
to
On 2009-12-01, Claus Reibenstein <4spame...@kabelmail.de> wrote:
> Thomas Koenig schrieb:

>>> Es liegt in der Verantwortung des Programmierers,


>>> solche Fᅵlle zu erkennen und zu behandeln.
>>
>> Genau, und meine Frage war, wie man das am besten macht, am relativ
>> einfachen Beispiel der Subtraktion zweier int-Zahlen, und zwar nach
>> den Regeln der C-Norm, ohne sich (z.B.) auf Zweierkomplement zu
>> verlassen.

> Eine Universallᅵsung gibt es nicht, auch keine "nach den Regeln der
> C-Norm", da die C-Norm fᅵr solche Fᅵlle nichts vorsieht.

Die C-Norm sieht fᅵr ᅵberlauf von ints nichts vor. Es sollte
jedoch durchaus mᅵglich sein, als Programmierer im Rahmen der C-Norm
entsprechende Maᅵnahmen zu ergreifen.

> Es hᅵngt von
> der jeweiligen Situation ab, welche Werte vorkommen,

In meinem Fall: Alle Werte, die garantiert (per C-Norm) in ein
int passen, also -INT_MAX bis INT_MAX.

> ob diese zu einem
> Overflow fᅵhren kᅵnnen

Kᅵnnten sie dann , logischerweise, z.B. bei

int a,b,c;

a = INT_MAX; b=-INT_MAX; c = a - b;

> und wie der abzufangen ist

Darum geht ja gerade, wie man das am besten macht, und zwar
"strictly conforming".

, und es hᅵngt von der
> Implementierung ab, was passiert, wenn es wirklich mal zu einem Overflow
> kommt.

Dazu will ich es ja gar nicht kommen lassen, und zwar mᅵchte ich
das innerhalb eines strictly conforming programs vermeiden.

Oder ist hier off-topic, wie man ein bestimmtes Problem innerhalb
der C-Norm lᅵst?

>> Multiplikation dᅵrfte noch ein bisschen schwieriger sein.
>
> Das Problem ist im Prinzip das gleiche.

Schon ein bisschen kniffliger.

Hier ist zuerst mal eine Funktion, mit der ich, AFAIK, zwei int sicher
voneinander abziehen kann. Wenn es einen ᅵberlauf gibt, dann wird der
signalisiert.

#include <limits.h>

/*
* Berechne a-b; im Falle eines ᅵberlaufs gebe INT_MAX mit dem richtigen
* Vorzeichen zurᅵck und setze *overflow zu 1. Ansonsten wird *overflow
* nicht verᅵndert.
*/

int minus(int a, int b, int *overflow)
{
unsigned int au, bu;

if (a >= 0) {
if (b < 0) {
au = a;
bu = -b;
if (au + bu > INT_MAX) {
*overflow = 1;
return INT_MAX;
}
}
} else { /* a < 0 */
if (b >= 0) {
au = -a;
bu = b;
if (au + bu > INT_MAX) {
*overflow = 1;
return -INT_MAX;
}
}
}

return a - b;
}

Irgendwelche Lᅵcken in der Funktion?

Michael Schumacher

unread,
Dec 4, 2009, 3:36:41 PM12/4/09
to
Thomas Koenig wrote:

> #include <limits.h>
>
> /*
> * Berechne a-b; im Falle eines Überlaufs gebe INT_MAX mit dem richtigen
> * Vorzeichen zurück und setze *overflow zu 1. Ansonsten wird *overflow
> * nicht verändert.


> */
>
> int minus(int a, int b, int *overflow)
> {
> unsigned int au, bu;
>
> if (a >= 0) {
> if (b < 0) {
> au = a;
> bu = -b;
> if (au + bu > INT_MAX) {
> *overflow = 1;
> return INT_MAX;
> }
> }
> } else { /* a < 0 */
> if (b >= 0) {
> au = -a;
> bu = b;
> if (au + bu > INT_MAX) {
> *overflow = 1;
> return -INT_MAX;
> }
> }
> }
>
> return a - b;
> }
>

> Irgendwelche Lücken in der Funktion?

Du meinst, außer dem (von mir im ersten if-Teil nur unzureichend
korrigierten OTBC), und daß sie flasche Rückgabewerte bei Überlauf
liefert? Nö... ;-)


mike

0 new messages