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

signed durch unsigned?

1 view
Skip to first unread message

Helmut Zeisel

unread,
Sep 28, 2009, 8:50:49 AM9/28/09
to
Wie dividiere ich standardkonform ein signed int s durch ein unsigned
int u, wenn ich ein signed int als Ergebnis haben will? s/u ist ja
unsigned, bei s<0 ist das Ergebnis anders als gewollt.

Helmut

Markus Wichmann

unread,
Sep 28, 2009, 1:00:43 PM9/28/09
to
Helmut Zeisel (zei2...@liwest.at) schrieb:

Caste u auf einen Typen, der zwar signed ist, aber in den alle Werte von
unsigned int reinpassen. Welcher Typ das ist, musst du mit sizeof selbst
rausfinden. Schlimmstenfalls nimmst du halt "long long".

Zumindest ist das der C-Ansatz. Sicherlich gibt es noch einen
C++-Ansatz mit boost oder der STL.

HTH,
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

Stefan Reuther

unread,
Sep 28, 2009, 4:32:14 PM9/28/09
to
Markus Wichmann wrote:
> Helmut Zeisel (zei2...@liwest.at) schrieb:
>>Wie dividiere ich standardkonform ein signed int s durch ein unsigned
>>int u, wenn ich ein signed int als Ergebnis haben will? s/u ist ja
>>unsigned, bei s<0 ist das Ergebnis anders als gewollt.
>
> Caste u auf einen Typen, der zwar signed ist, aber in den alle Werte von
> unsigned int reinpassen. Welcher Typ das ist, musst du mit sizeof selbst
> rausfinden. Schlimmstenfalls nimmst du halt "long long".

"long long" gibt's nur dummerweise offiziell in C++ noch nicht, so dass
man dann gleich floating-point nehmen darf oder sich das Ergebnis zu Fuß
zusammenbasteln.

Bei s/u kann man allerdings auch recht einfach vergleichen:
- wenn s = INT_MIN, u = -INT_MIN, ist das Ergebnis -1
- sonst, wenn u > INT_MAX, dann ist das Ergebnis Null
- sonst s/int(u)

> Zumindest ist das der C-Ansatz. Sicherlich gibt es noch einen
> C++-Ansatz mit boost oder der STL.

Naja, C++ gibt einem halt die Möglichkeit, das ganze in eine hübsche
Templatefunktion zu verpacken.


Stefan

Falk Tannhäuser

unread,
Sep 28, 2009, 5:01:20 PM9/28/09
to
Helmut Zeisel schrieb:

> Wie dividiere ich standardkonform ein signed int s durch ein unsigned
> int u, wenn ich ein signed int als Ergebnis haben will? s/u ist ja
> unsigned, bei s<0 ist das Ergebnis anders als gewollt.

int ergebnis = u <= unsigned(std::numeric_limits<int>::max()) ? s/int(u) : 0;

sollte es tun - ist u zu gro�, um in einen int zu passen, kann sowieso nur 0 rauskommen.

MfG
Falk

James Kanze

unread,
Sep 29, 2009, 3:30:21 AM9/29/09
to
On Sep 28, 9:32 pm, Stefan Reuther <stefan.n...@arcor.de> wrote:
> Markus Wichmann wrote:
> > Helmut Zeisel (zei200...@liwest.at) schrieb:

> >>Wie dividiere ich standardkonform ein signed int s durch ein
> >>unsigned int u, wenn ich ein signed int als Ergebnis haben
> >>will? s/u ist ja unsigned, bei s<0 ist das Ergebnis anders
> >>als gewollt.

> > Caste u auf einen Typen, der zwar signed ist, aber in den
> > alle Werte von unsigned int reinpassen. Welcher Typ das ist,
> > musst du mit sizeof selbst rausfinden. Schlimmstenfalls
> > nimmst du halt "long long".

> "long long" gibt's nur dummerweise offiziell in C++ noch
> nicht,

Offiziell nicht. In der Praxis aber doch. Ich hätte schon Heute
keine Hemmungen dagegen, es zu benutzen.

> so dass man dann gleich floating-point nehmen darf oder
> sich das Ergebnis zu Fuß zusammenbasteln.

> Bei s/u kann man allerdings auch recht einfach vergleichen:
> - wenn s = INT_MIN, u = -INT_MIN, ist das Ergebnis -1
> - sonst, wenn u > INT_MAX, dann ist das Ergebnis Null
> - sonst s/int(u)

Es besteht auch die Möglichkeit, dass man die Quelle des
unsigned kennt, und weiß im Voraus, dass es kleiner als INT_MAX
ist. Wenn nicht aber... muss man vorsichtig beim Schreiben des
Vergleichs mit -INT_MAX sein. In C++ (und C), der Ausdruck
-INT_MAX ergibt nicht, was man erwartet. (Laut §5/4 soll er
sogar auf den meisten Rechnern nicht ohne Fehler compilieren.)

> > Zumindest ist das der C-Ansatz. Sicherlich gibt es noch einen
> > C++-Ansatz mit boost oder der STL.

> Naja, C++ gibt einem halt die Möglichkeit, das ganze in eine
> hübsche Templatefunktion zu verpacken.

Warum einfach machen, wenn man kompliziert machen kann?:-)

--
James Kanze

Helmut Zeisel

unread,
Sep 29, 2009, 6:34:08 AM9/29/09
to
On Sep 28, 11:01 pm, Falk Tannhäuser <tannhauser86549s...@free.fr>
wrote:

> Helmut Zeisel schrieb:
>
> > Wie dividiere ich standardkonform ein signed int s durch ein unsigned
> > int u, wenn ich ein signed int als Ergebnis haben will? s/u ist ja
> > unsigned, bei s<0 ist das Ergebnis anders als gewollt.
>
> int ergebnis = u <= unsigned(std::numeric_limits<int>::max()) ? s/int(u) : 0;
>
> sollte es tun - ist u zu groß, um in einen int zu passen, kann sowieso nur 0 rauskommen.

Nein, INT_MIN ist meist -INT_MAX-1, also INT_MIN/u = -1 für u=INT_MAX
+1.

Richtig interessant wird dann die Frage, was man macht, wenn INT_MIN
nicht -INT_MAX-1 ist.

Helmut

Helmut Zeisel

unread,
Sep 29, 2009, 6:28:08 AM9/29/09
to
On Sep 28, 10:32 pm, Stefan Reuther <stefan.n...@arcor.de> wrote:

> Bei s/u kann man allerdings auch recht einfach vergleichen:
> - wenn s = INT_MIN, u = -INT_MIN, ist das Ergebnis -1
> - sonst, wenn u > INT_MAX, dann ist das Ergebnis Null
> - sonst s/int(u)

Garantiert der Standard, dass INT_MIN=-INT_MAX-1?

Helmut

Helmut Zeisel

unread,
Sep 29, 2009, 6:24:55 AM9/29/09
to
On Sep 28, 7:00 pm, Markus Wichmann <nullp...@gmx.net> wrote:

> Schlimmstenfalls nimmst du halt "long long".

Dann habe ich das gleiche Problem z.B. bei long long / unsigned long
long

Helmut

Olaf Krzikalla

unread,
Sep 29, 2009, 9:31:53 AM9/29/09
to
Helmut Zeisel schrieb:

> Wie dividiere ich standardkonform ein signed int s durch ein unsigned
> int u, wenn ich ein signed int als Ergebnis haben will? s/u ist ja
> unsigned, bei s<0 ist das Ergebnis anders als gewollt.

Probier ich mich auch mal:

return s < 0 ? (-((-s)/u)) : s/u;


MfG
Olaf Krzikalla

SG

unread,
Sep 29, 2009, 10:02:40 AM9/29/09
to
On 29 Sep., 12:28, Helmut Zeisel wrote:
>
> Garantiert der Standard, dass INT_MIN=-INT_MAX-1?

Nein. Er gibt nur untere Schranken für die Beträge von XXX_MIN und
XXX_MAX an. Und die sind zB für INT folgende:

INT_MIN <= -32767
INT_MAX >= 32767

Dass ich nicht -32768 geschrieben habe ist kein Fehler. Das
Zweierkomplement wird nicht erzwungen. Eine konforme Implementierung
darf auch das Einerkomplement oder Sign+Magnitude benutzen. Die
Darstellung negativer Zahlen ist also strenggenommen
implementierungsabhängig.

Allerdings wird in C++0x der Header <cstdint> eingeführt, der wie der
C99-Header <stdint.h> typedefs für "exact width integers"
bereitstellen kann. Die sind zwar optional, garantieren aber bei
Existenz das Zweierkomplement. Wenn also Dein Programm int32_t benutzt
und es kompiliert, kannst Du Dir auch sicher sein, dass das
Zweierkomplement verwendet wird.

Gruß,
SG

Stefan Reuther

unread,
Sep 29, 2009, 1:16:10 PM9/29/09
to

Nein. Allerdings kann man m.W. aus den Forderungen, die an Integer-Typen
gestellt werden (pure binary numeration system, unsigned mod 2^n)
ableiten, dass nur eins von drei Zahlensystemen eingesetzt wird:
Zweierkomplement (INT_MIN = -INT_MAX-1) oder Einerkomplement bzw.
Sign-Magnitude (INT_MIN = -INT_MAX).


Stefan

Helmut Zeisel

unread,
Sep 30, 2009, 3:53:42 AM9/30/09
to
On Sep 29, 3:31 pm, Olaf Krzikalla <krzika...@gmx.de> wrote:

> return s < 0 ? (-((-s)/u)) : s/u;

Da gibt es keine Garantie, dass das insbesondere für s=INT_MIN
funktioniert.

Helmut

Helmut Zeisel

unread,
Sep 30, 2009, 6:32:17 AM9/30/09
to
On Sep 29, 7:16 pm, Stefan Reuther <stefan.n...@arcor.de> wrote:

> > Garantiert der Standard, dass INT_MIN=-INT_MAX-1?
>
> Nein. Allerdings kann man m.W. aus den Forderungen, die an Integer-Typen
> gestellt werden (pure binary numeration system, unsigned mod 2^n)
> ableiten, dass nur eins von drei Zahlensystemen eingesetzt wird:
> Zweierkomplement (INT_MIN = -INT_MAX-1) oder Einerkomplement bzw.
> Sign-Magnitude (INT_MIN = -INT_MAX).

Meinst Du mit ableiten "ich kann mir keine andere Implementierung
vorstellen" oder "der Standard garantiert"?

Helmut

Helmut Zeisel

unread,
Sep 30, 2009, 4:00:58 AM9/30/09
to
On Sep 29, 9:30 am, James Kanze <james.ka...@gmail.com> wrote:

> Es besteht auch die Möglichkeit, dass man die Quelle des
> unsigned kennt, und weiß im Voraus, dass es kleiner als INT_MAX
> ist. Wenn nicht aber... muss man vorsichtig beim

Genau um den Fall geht es. Ich weiß nicht, ob der unsigned Wert
kleiner als INT_MAX( bzw. LONG_MAX oder LLONG_MAX) ist.
Ich weiß lediglich, dass der unsigned Wert von Null verschieden ist.
Das Ergebnis s/u ist dann jedenfalls im zulässigen Bereich.
Was nun?

Vielleicht hat bei der Gelegenheit auch jemand für s%u eine Lösung ...

Helmut

James Kanze

unread,
Sep 30, 2009, 3:45:40 AM9/30/09
to

Möglicherweise undefiniertes Verhalten, wenn s == INT_MIN.

--
James Kanze

Stefan Reuther

unread,
Sep 30, 2009, 12:22:54 PM9/30/09
to

Mir f�llt zumindest beim besten Willen keine ein, die die Forderungen
des Standards erf�llt. Okay, eine: ein Zahlensystem, wo die negativen
Werte z.B. von 0x999999 .. 0xFFFFFF und die positiven von 0x000000 ..
0x999998 gehen, also wie Zweierkomplement, nur mit verschobenen Grenzen.
Allerdings kann man da dann dem h�chstwertigen Bit keinen Wert mehr
zuordnen, wie es sich f�r ein Positionssystem eigentlich geh�rt.

Davon abgesehen wird's nat�rlich knifflig, einen Hardwerker zu finden,
der einen Prozessor mit solchen Perversit�ten baut :-)


Stefan

Thomas Thiele

unread,
Sep 30, 2009, 6:38:01 PM9/30/09
to
Helmut Zeisel schrieb:

> Genau um den Fall geht es. Ich wei� nicht, ob der unsigned Wert

> Vielleicht hat bei der Gelegenheit auch jemand f�r s%u eine L�sung ...


Ich versteh das Problem nicht.
Mach den signed Wert einfach positiv, rechne mit unsigned Werten und
mach das Ergebnis geg. wieder negativ.

int div(unsigned int u, int s){
if (s > 0){
return u / static_cast<unsigned int>(s);
}
else if (s < 0){
return -(u / static_cast<unsigned int>(-s));
}
else{
//div durch 0
return 0;
}
}

James Kanze

unread,
Oct 1, 2009, 4:19:10 AM10/1/09
to

Die C++ Norm sagt es nicht so genau, die C Norm aber doch. Laut
C99 sind nur drei Möglichkeiten erlaubt, Zweierkomplement,
Einerkomplement oder Sign-Magnitude. Darüber gibt es DR in C++.
(Als C++ die Spezifikation von C90 übernommen hat, haben die
Autoren ein Paar Änderungen im Text gemacht, die eine
C-Implementierungen nicht in C++ erlauben. Was nicht den Ziel
war.)

--
James Kanze

Helmut Zeisel

unread,
Oct 1, 2009, 1:33:55 AM10/1/09
to
On 1 Okt., 00:38, Thomas Thiele <thomas.thi...@gmx.de> wrote:

> Ich versteh das Problem nicht.
> Mach den signed Wert einfach positiv,

Funktioniert das auch für -INT_MIN > INT_MAX ?

Helmut

Helmut Zeisel

unread,
Oct 1, 2009, 3:15:25 AM10/1/09
to
On Oct 1, 12:38 am, Thomas Thiele <thomas.thi...@gmx.de> wrote:

> Ich versteh das Problem nicht.

Du hast mich aber anscheinend auf die richtige Spur gebracht.

>      return -(u / static_cast<unsigned int>(-s));

Wie schon andernorts gesagt: static_cast<unsigned int>(-s) fuktioniert
nicht zwingend, wenn s=INT_MIN.
Die zielführende Frage ist aber, wie rechnet man static_cast<unsigned
int>(-s) richtig.
static_cast<unsigned int> rechnet Arithemetik modulo m=2^n, für
negative s ist also

static_cast<unsigned int>(s) = m+s

modulo m gilt also

-s = m-(m+s) = m-static_cast<unsigned int>(s) = -
static_cast<unsigned int>(s)

Das schaut auf den ersten Blick wie ein Tippfehler aus, ist aber auf
dem zweiten Blick eine elegante Lösung.

Die betreffende Zeile muss dann also

return -static_cast<int>(u / (-static_cast<unsigned int>(s)));

lauten. Hab ich was uebersehen?

Helmut

0 new messages