Toon posts:

[C++] int - unsigned

Pagina: 1
Acties:

Verwijderd

Topicstarter
nedint - unsigned int werkt niet helemaal lekker. Nou lukt het me wel om het op te lossen. Maar ik snap niet waarom dit niet werkt. Ik hoop dat 1 van jullie het kan verklaren.

Ik heb het volgende stukje code
code:
1
2
3
4
5
6
7
8
void banking::withdraw(unsigned int amount)
{
  // current_balance is een signed int
     if ( (current_balance - amount) >= -2000)
      current_balance -= amount;
    else cout << "You have: " << current_balance
            << " you can not withdraw over -2000"  << endl;
}

Als mijn current_balance op 5000 staat en ik haal er 4000 van af is er geen probleem. Dan is de if statement er dus mee eens dat 5000 - 4000 >= -2000.

Als ik echter mijn current_balance op 5000 set en ik haal er 6000 van af. Dan werkt het niet meer. de if statement is er dan niet mee eens dat 5000 - 6000 >= -2000.

Vermoed dat het met de unsigned int te maken heeft. Maar waarom weet ik niet. Iemand een idee?

  • Wokker
  • Registratie: September 2001
  • Laatst online: 06:17

Wokker

De avond wokkel

unsigned int is volgens mij alleen maar voor positieve getallen.
Dus maak er maar gewoon int van (of ik heb het fout)

Het oneindige X 0


  • General_Failure
  • Registratie: Oktober 2000
  • Laatst online: 15-09 16:08

General_Failure

Vrolijk Pasen!!!

Unsigned betekent geen teken, dus een int die altijd > 0 is. Er gaat iets fout doordat jij een unsigned int met een gewone int < 0 vergelijkt.
Haal unsigned weg en het werkt (voor getallen tot 32000, anders moet je long gebruiken).

Me and my dear friend General Protection-Error will invade your computer with our mighty army of Bugs. We will avoid the Firewall at the Gates of your PC by entering through your Windows.


  • Apache
  • Registratie: Juli 2000
  • Laatst online: 14-09 22:46

Apache

amateur software devver

Op donderdag 13 december 2001 11:21 schreef Wokker het volgende:
unsigned int is volgens mij alleen maar voor positieve getallen.
Dus maak er maar gewoon int van (of ik heb het fout)
klopt, maar je withdraw zal steeds positief zijn :)

rekening zelf daarentegen hou je best gewoon int (of float oid)

Jammer genoeg ben ik enkel nog maar ff met C bezig geweest, en daar heb ik enkel nog maar parameters doorgegeven zonder ze te definieren (php slordigheidje)

If it ain't broken it doesn't have enough features


Verwijderd

Eh, het is echt niet noodzakelijk om het argument van type te laten veranderen.

Je gebruikt in een expressie zowel signed int als unsigned int. Hierdoor is het het type van het resultaat niet bepaald en blijkbaar kiest de compiler voor unsigned int.

Je moet in alle expressie's ervoor zorgen dat de types aan elkaar gelijk zijn. In dit geval kan je het beste amount converteren naar int. oftewel:
(current_balance - (const signed int)amount)

Waarom die const?
Mnou, het argument van een functie/procedure hoort const te wezen als je em niet wijzigd. Argumenten wijzigen is normaal gezien trouwens onverstandig >:)

De functie zou eigenlijk moeten zijn:
void banking::withdraw(CONST unsigned int amount)

Consequent aangeven wat constante's zijn levert meer performance maar (belangrijker) als je de functie na lange tijd nog een keer nodig hebt geeft het duidelijker aan wat het doet.

Succes

  • Wokker
  • Registratie: September 2001
  • Laatst online: 06:17

Wokker

De avond wokkel

Maar ik heb een vraagje
Waarom maak je niet in je gehele script van amount een int ?? OMdat amount ook negatief kan zijn toch
want je kan altijd rood staan.

Het oneindige X 0


Verwijderd

Topicstarter
Op donderdag 13 december 2001 11:35 schreef Ferguras het volgende:
Je gebruikt in een expressie zowel signed int als unsigned int. Hierdoor is het het type van het resultaat niet bepaald en blijkbaar kiest de compiler voor unsigned int.
Ik had niet verwacht dat de compiler een voor een unsigned int zou kiezen. Vawege het feit dat ie dit wel pikt.
float = float - int
int = int - unsigned int

achter af gezien, nu heb ik al links van het = teken gedifineerd dat het een flaot of int moet worden.

dan zou als ik dit doe het wel moeten werken
code:
1
2
3
4
int getal = -2000;
blabla
current_balance - amount) >= getal
blabla

FF testen...
Ja dat wekt wel

Als ik dus gewoon -2000 gebruik achter >=. Dan ziet de compiler -2000 alleen als een int als current_balance - amount kleiner wordt dan 0. Als dus current_balance - amount groter wordt dan 0 dan ziet de compiler -2000 als 2000. Tovert ie het - teken gewoon weg.

Dit was trouwens in een VisualAge C++ compiler. Vanavond ff testen met mijn Borland TC++.

Verwijderd

Topicstarter
Op donderdag 13 december 2001 12:01 schreef Wokker het volgende:
Maar ik heb een vraagje
Waarom maak je niet in je gehele script van amount een int ?? OMdat amount ook negatief kan zijn toch
want je kan altijd rood staan.
1. in de opgave stond dat het een unsigned moest zijn.
2. amount kan niet negatief zijn omdat amount een bedrag is wat je van je rekening opneemt. (via pin of de bank zelf.) current_balance is het huidige saldo

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 23:11
Op donderdag 13 december 2001 11:35 schreef Ferguras het volgende:
Je gebruikt in een expressie zowel signed int als unsigned int. Hierdoor is het het type van het resultaat niet bepaald en blijkbaar kiest de compiler voor unsigned int.
Sorry, maar dat is onzin.
Het resultaat van binaire operators op een signed en een unsigned int is duidelijk bepaald, en is unsigned int.
" Otherwise, if either operand is unsigned, the other shall be converted to unsigned. "
Dus eerst worden allebei de kanten van de - unsigned it, het resultaat is dan ook unsigned, en vervolgens wordt -2000 een unsigned, met waarde UINT_MAX-2000 (=groot)
(Ok, ik heb het toch effe opgezocht :) )
Je moet in alle expressie's ervoor zorgen dat de types aan elkaar gelijk zijn. In dit geval kan je het beste amount converteren naar int. oftewel:
(current_balance - (const signed int)amount)
Je hoeft er niet voor te zorgen. Het is wel verstandig, zeker bij het gebruik van >, om dat te doen, omdat het dan zichtbaar is welke typen gebruikt worden. Houd er wel rekening mee dat er gekke dingen gebeuren als je unsigned int groter is dan INT_MAX.

PS. Gebruik in C++ geen C-style casts. De goede cast is
code:
1
 static_cast<const int>( amount )

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Orphix
  • Registratie: Februari 2000
  • Niet online
Gebruik in het algemeen (als je geen bitwise operaties doet) geen unsigned int, maar gewoon int.

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Waarom zou je met bitwise ops ineens wel unsigned nemen dan?

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Op donderdag 13 december 2001 11:23 schreef General_Failure het volgende:
Haal unsigned weg en het werkt (voor getallen tot 32000, anders moet je long gebruiken).
Waarom zou int 16-bit zijn?

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Op donderdag 13 december 2001 17:17 schreef OlafvdSpek het volgende:

[..]

Waarom zou int 16-bit zijn?
Verschilt per platform.

print gewoon het resultaat van sizeof(int) en je weet het zeker.

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Op donderdag 13 december 2001 17:17 schreef OlafvdSpek het volgende:
Waarom zou je met bitwise ops ineens wel unsigned nemen dan?
Omdat je dan als je een getal van 10 erin propt ook weet hoe het er bitwise uitziet. En bij een getal als 0 weet je dan dat alle bits op 0 staan. Dit kan handig zijn voor flags of om bits op te slaan in een array van (unsigned) int.

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Op donderdag 13 december 2001 23:48 schreef Orphix het volgende:

[..]

Omdat je dan als je een getal van 10 erin propt ook weet hoe het er bitwise uitziet. En bij een getal als 0 weet je dan dat alle bits op 0 staan. Dit kan handig zijn voor flags of om bits op te slaan in een array van (unsigned) int.
En stel dat je zo slim bent om een signed en unsigned bitwise te gaan combineren. Voor je het weet heb je een fout die echt extreem lastig terug te vinden is.

Verwijderd

Op donderdag 13 december 2001 16:34 schreef Orphix het volgende:
Gebruik in het algemeen (als je geen bitwise operaties doet) geen unsigned int, maar gewoon int.
Als je dat doet met je compiler op warning-level extreme paranoia (ofzo) dan regent het warnings. Elke keer als je een signed met een unsigned waarde vergelijkt is het prijs, en dat gebeurt nogal eens op systemen waar het size_t type een unsigned is.

Overigens zou ik het oplossen door maar een keer de berekening te maken, en die te assignen als die in de range valt, dus zoiets:
code:
1
2
3
4
5
6
7
8
void banking::withdraw(unsigned amount)
{
     int new_balance = current_balance - amount;
     if ( new_balance >= -2000 && new_balance <= current_balance)
      current_balance = new_balance;
    else cout << "You have: " << current_balance
            << " you can not withdraw over -2000"  << endl;
}

Die tweede vergelijking is om te garanderen dat er geen overflow underflow heeft plaatsgevonden (dan is het opgenomen bedrag in ieder geval te groot).

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Op vrijdag 14 december 2001 00:34 schreef The - DDD het volgende:
En stel dat je zo slim bent om een signed en unsigned bitwise te gaan combineren. Voor je het weet heb je een fout die echt extreem lastig terug te vinden is.
Eh ja, wat wil je dus .. beiden gebruiken of alleen signed :?

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Ik bedoelde eigenlijk dat je beter geen unsigned int kan nemen om een groter bereik te halen. Dit wordt nml teniet gedaan door de vele (impliciete) conversies.
(disclaimer: dit komt bijna direct van b. stroustrup hoor, niet echt zelf bedacht :))

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Op donderdag 13 december 2001 23:48 schreef Orphix het volgende:

[..]

Omdat je dan als je een getal van 10 erin propt ook weet hoe het er bitwise uitziet. En bij een getal als 0 weet je dan dat alle bits op 0 staan. Dit kan handig zijn voor flags of om bits op te slaan in een array van (unsigned) int.
Of je 10 nou in een unsigned of signed stopt, het ziet er toch hetzelfde uit.

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Op vrijdag 14 december 2001 00:34 schreef The - DDD het volgende:

[..]

En stel dat je zo slim bent om een signed en unsigned bitwise te gaan combineren. Voor je het weet heb je een fout die echt extreem lastig terug te vinden is.
Heb je daar een voorbeeld van?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:17

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op vrijdag 14 december 2001 21:10 schreef OlafvdSpek het volgende:

[..]

Heb je daar een voorbeeld van?
mmja het enige voorbeeld wat ik kan bedenken is dat als je een shift right op een signed getal uitvoert op een negatief getal (dwz, de msb is geset), dat ie dan gaat padden met enen ipv met nullen (hangt overigens ook van het ontwikkelplatform af, aangezien in de C++ niet is gedefinieerd of shifts logical of arithmetic zijn)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Niet gedefined? Ik denk van wel. Logical op unsigned, arithmetic op signed.

En als je daarna alles goed masked (&) dan maakt het nog niet uit.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 23:11
Op donderdag 13 december 2001 17:17 schreef OlafvdSpek het volgende:

[..]

Waarom zou int 16-bit zijn?
Dat is de foute vraag.
De correcte vraag is, waarom zou int MINIMAAL 16 bits zijn?
En dat is omdat K&R dat besloten hebben.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Op zaterdag 15 december 2001 11:07 schreef MSalters het volgende:

[..]

Dat is de foute vraag.
De correcte vraag is, waarom zou int MINIMAAL 16 bits zijn?
En dat is omdat K&R dat besloten hebben.
Hoezo foute vraag? Volgens mij is dat de goede vraag. Ik wilde er mee aangeven dat int geen 16-bit hoeft te zijn.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 23:11
Op zaterdag 15 december 2001 13:23 schreef OlafvdSpek het volgende:

[..]

Hoezo foute vraag? Volgens mij is dat de goede vraag. Ik wilde er mee aangeven dat int geen 16-bit hoeft te zijn.
Dat laatste klopt, maar de vraag die je stelde was misleidend. De originele post ging niet over het aantal bits in een int, maar over het MINIMALE aantal bits in een int. En dat is wel 16 => range is [-32767,32767]
( -32767 ivm -0/+0 systemen )

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
> Haal unsigned weg en het werkt (voor getallen tot 32000, anders moet je long gebruiken).

Dat geeft aan dat int maximaal 16-bit zou zijn. Of zie ik dat nou verkeerd?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:17

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zaterdag 15 december 2001 11:06 schreef OlafvdSpek het volgende:
Niet gedefined? Ik denk van wel. Logical op unsigned, arithmetic op signed.

En als je daarna alles goed masked (&) dan maakt het nog niet uit.
dat staat dus niet in de standaard :)
ja, zo werkt het onder vrijwel alle platformen, maar het hoeft niet zo te werken, omdat het nou eenmaal niet in de standaard staat

het is hetzelfde verhaal als bij de bitgrootte van char, short en long: ze zijn vrijwel altijd 8, 16 en 32 bits lang, maar dat staat dus ook niet in de standaard, dus dat hoeft ook niet zo te zijn... het enige wat is afgesproken is dat sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long), en dat sizeof (char) == 1

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1