/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
Bech_bb 500
kyllekylle 500
jdjespers.. 500
gibson 300
scootergr.. 300
molokyle 287
10  strarup 270
Underligt eller er det bare mig der gør de~
Fra : Morten Larsen


Dato : 27-08-05 11:44

Jeg har følgende kode:

unsigned long addr;
int a,b,c,d;
a = 192;
b = 168;
c = 1;
d = 1;
addr = ( (a * pow(256,3)) + (b * pow(256,2)) + (c * pow(256,1)) + (d
* pow(256,0)) );

Hvis jeg åbner borland c++ builder, og indsætter ovenstående kode i en form
får addr det ønskede resultat.
Men indsætter jeg koden i et C program (ikke c++), får addr et forkert
resultat. dvs. at udregningerne bliver forkerte. Mit problem er så at denne
formel skal regnes i et C program og det er ikke en mulighed for at gører
dette i c++, da programmet skal være i C.

Håber nogen har en ide om hvad der går galt?

//Morten



 
 
Mogens Hansen (27-08-2005)
Kommentar
Fra : Mogens Hansen


Dato : 27-08-05 12:16


"Morten Larsen" <not@4u.com> wrote in message
news:431043fa$0$37101$edfadb0f@dread12.news.tele.dk...

[8<8<8<]
> Mit problem er så at denne formel skal regnes i et C program og det er
> ikke en mulighed for at gører dette i c++, da programmet skal være i C.

Hvis du oversætter det med C++Builder som C går det også fint.

Der er den forskel på C og C++ programmet at i C findes der kun een "pow"
funktion:
double pow(double, double);
I C++ er der en række overloads:
float pow (float, float);
float pow (float, int);
double pow(double, int);
long double pow (long double, long double);
long double pow (long double, int);
template<class T> complex<T> pow(const complex<T>&, int);
template<class T> complex<T> pow(const complex<T>&, const T&);
template<class T> complex<T> pow(const complex<T>&, const complex<T>&);
template<class T> complex<T> pow(const T&, const complex<T>&);
template<class T> valarray<T> pow(const T&, const valarray<T>&);
template<class T> valarray<T> pow(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> pow (const valarray<T>&, const T&);
template<class T> valarray<T> pow (const T&, const valarray<T>&);

Det er den 2. eller 3. der bliver brugt i dit program.

>
> Håber nogen har en ide om hvad der går galt?

Hvor stor er en unsigned long på den anden platform ?

Hvorfor bruger du egentlig en runtime beregning, når det egentlig er compile
time konstanter og du går endda over floating point beregning.
Et alternativ er
addr = a*16777216 + b*65536 + c*256 +d;
eller måske endnu tydeligere
addr = (((unsigned long) a) << 24) +
(((unsigned long) b) << 16) +
(((unsigned long) c) << 8) +
(((unsigned long) d) << 0);

Det er langt tydeligere hvad det laver og det kører formodentlig også
hurtigere.

Venlig hilsen

Mogens Hansen



Morten Larsen (27-08-2005)
Kommentar
Fra : Morten Larsen


Dato : 27-08-05 12:53


"Mogens Hansen" <mogens_h@dk-online.dk> skrev i en meddelelse
news:43104b8e$0$78284$157c6196@dreader1.cybercity.dk...
>
> "Morten Larsen" <not@4u.com> wrote in message
> news:431043fa$0$37101$edfadb0f@dread12.news.tele.dk...
>
> [8<8<8<]
>> Mit problem er så at denne formel skal regnes i et C program og det er
>> ikke en mulighed for at gører dette i c++, da programmet skal være i C.
>
> Hvis du oversætter det med C++Builder som C går det også fint.
>
> Der er den forskel på C og C++ programmet at i C findes der kun een "pow"
> funktion:
> double pow(double, double);
> I C++ er der en række overloads:
> float pow (float, float);
> float pow (float, int);
> double pow(double, int);
> long double pow (long double, long double);
> long double pow (long double, int);
> template<class T> complex<T> pow(const complex<T>&, int);
> template<class T> complex<T> pow(const complex<T>&, const T&);
> template<class T> complex<T> pow(const complex<T>&, const complex<T>&);
> template<class T> complex<T> pow(const T&, const complex<T>&);
> template<class T> valarray<T> pow(const T&, const valarray<T>&);
> template<class T> valarray<T> pow(const valarray<T>&, const
> valarray<T>&);
> template<class T> valarray<T> pow (const valarray<T>&, const T&);
> template<class T> valarray<T> pow (const T&, const valarray<T>&);
>
> Det er den 2. eller 3. der bliver brugt i dit program.
>
>>
>> Håber nogen har en ide om hvad der går galt?
>
> Hvor stor er en unsigned long på den anden platform ?
>
> Hvorfor bruger du egentlig en runtime beregning, når det egentlig er
> compile time konstanter og du går endda over floating point beregning.
> Et alternativ er
> addr = a*16777216 + b*65536 + c*256 +d;
> eller måske endnu tydeligere
> addr = (((unsigned long) a) << 24) +
> (((unsigned long) b) << 16) +
> (((unsigned long) c) << 8) +
> (((unsigned long) d) << 0);
>
> Det er langt tydeligere hvad det laver og det kører formodentlig også
> hurtigere.

Du har helt ret i ovenstående undtagen at det dog er den rigtige pow der
bruges
Jeg har prøvet en del i C, for at få det til at virke.
Men problemet er ikke i pow, tror snare det er * (gange) der driller.

Min udregning: -1062731519
Din nummer 1: -1062731519
Dim nummer 2: -1062731519

Men resultatet i cpp og andre sprog jeg har testet i, bliver resultatet
ikke -1062731519 men 32322355777.
Jeg vil gerne have det samme resultat i C :) Så håber du kan hjælpe mig med
det?

Jeg vil formentlig også lide under dette problem når jeg konvertere tilbage.

a = floor( addr / pow(256,3) );
b = floor( (addr % (int)pow(256,3)) / pow(256,2) );
c = floor( ( (addr % (int)pow(256,3)) % (int)pow(256,2) ) /
pow(256,1) );
d = floor( ( ( (addr % (int)pow(256,3)) % (int)pow(256,2) ) %
(int)pow(256,1) ) / pow(256,0) );

Ovenstående har du sikkert også en nemmere og bedre måde at gøre på?

//Morten



Kent Friis (27-08-2005)
Kommentar
Fra : Kent Friis


Dato : 27-08-05 13:02

Den Sat, 27 Aug 2005 13:53:24 +0200 skrev Morten Larsen:
>
> Jeg har prøvet en del i C, for at få det til at virke.
> Men problemet er ikke i pow, tror snare det er * (gange) der driller.
>
> Min udregning: -1062731519
> Din nummer 1: -1062731519
> Dim nummer 2: -1062731519
>
> Men resultatet i cpp og andre sprog jeg har testet i, bliver resultatet
> ikke -1062731519 men 32322355777.
>
> Jeg vil gerne have det samme resultat i C :) Så håber du kan hjælpe mig med
> det?

Det svarede han faktisk også på, hvis du læser *hele* svaret.

> Jeg vil formentlig også lide under dette problem når jeg konvertere tilbage.
>
> a = floor( addr / pow(256,3) );
> b = floor( (addr % (int)pow(256,3)) / pow(256,2) );
> c = floor( ( (addr % (int)pow(256,3)) % (int)pow(256,2) ) /
> pow(256,1) );
> d = floor( ( ( (addr % (int)pow(256,3)) % (int)pow(256,2) ) %
> (int)pow(256,1) ) / pow(256,0) );
>
> Ovenstående har du sikkert også en nemmere og bedre måde at gøre på?

and (&), shift right (>>).

Skal vi gætte på du er matematiker og ikke programmør? Den måde du
gør det på er matematisk korrekt, det der bare ikke den en programmør
ville vælge, da bit-operationerne (shift left/right, and, or, xor, not)
er beregnet specifikt til formålet, og nemmere for både mennesker og
computere at forstå.

Mvh
Kent
--
Hard work may pay off in the long run, but laziness pays off right now.

Morten Larsen (27-08-2005)
Kommentar
Fra : Morten Larsen


Dato : 27-08-05 13:36


"Kent Friis" <nospam@nospam.invalid> skrev i en meddelelse
news:43105620$0$18650$14726298@news.sunsite.dk...
> Den Sat, 27 Aug 2005 13:53:24 +0200 skrev Morten Larsen:

>> Jeg vil gerne have det samme resultat i C :) Så håber du kan hjælpe mig
>> med
>> det?
>
> Det svarede han faktisk også på, hvis du læser *hele* svaret.

I må meget undskylde, men så kan jeg altså ikke se det :)
Mogens gav 2 andre eksempler på hvordan det kan gøres.
Jeg prøvede dem, men resultatet er stadig det samme.
Det jeg ikke forstår er hvorfor addr bliver lig med "-1062731519" i C.
Når de samme udregninger (min måde, og mogens' 2 måder) i C++ bliver lig med
"32322355777"

>> Jeg vil formentlig også lide under dette problem når jeg konvertere
>> tilbage.
>>
>> a = floor( addr / pow(256,3) );
>> b = floor( (addr % (int)pow(256,3)) / pow(256,2) );
>> c = floor( ( (addr % (int)pow(256,3)) % (int)pow(256,2) ) /
>> pow(256,1) );
>> d = floor( ( ( (addr % (int)pow(256,3)) % (int)pow(256,2) ) %
>> (int)pow(256,1) ) / pow(256,0) );
>>
>> Ovenstående har du sikkert også en nemmere og bedre måde at gøre på?
>
> and (&), shift right (>>).

Mange tak, men ville ønske jeg vidste hvordan jeg skulle bruge dem :)

> Skal vi gætte på du er matematiker og ikke programmør? Den måde du
> gør det på er matematisk korrekt, det der bare ikke den en programmør
> ville vælge, da bit-operationerne (shift left/right, and, or, xor, not)
> er beregnet specifikt til formålet, og nemmere for både mennesker og
> computere at forstå.

Jeg vil hverken kalde mig for matematiker eller pro programmør :)
Jeg sad med problemet at skulle arbejde med ip ranges.
Efter søgning på google fandt jeg den formel jeg brugte i mit første indlæg.
Men kan fornemme at jeg skal lære lidt bit-operationer :)

//Morten



Mogens Hansen (27-08-2005)
Kommentar
Fra : Mogens Hansen


Dato : 27-08-05 13:46


"Morten Larsen" <not@4u.com> wrote in message
news:43105e38$0$25947$edfadb0f@dread12.news.tele.dk...
>
> "Kent Friis" <nospam@nospam.invalid> skrev i en meddelelse
> news:43105620$0$18650$14726298@news.sunsite.dk...
>> Den Sat, 27 Aug 2005 13:53:24 +0200 skrev Morten Larsen:
>
>>> Jeg vil gerne have det samme resultat i C :) Så håber du kan hjælpe mig
>>> med
>>> det?
>>
>> Det svarede han faktisk også på, hvis du læser *hele* svaret.
>
> I må meget undskylde, men så kan jeg altså ikke se det :)

Jeg skrev:
"Hvis du oversætter det med C++Builder som C går det også fint."

Venlig hilsen

Mogens Hansen



Michael Rasmussen (27-08-2005)
Kommentar
Fra : Michael Rasmussen


Dato : 27-08-05 13:53

On Sat, 27 Aug 2005 14:36:18 +0200, Morten Larsen wrote:


> Jeg vil hverken kalde mig for matematiker eller pro programmør :) Jeg
> sad med problemet at skulle arbejde med ip ranges. Efter søgning på
> google fandt jeg den formel jeg brugte i mit første indlæg. Men kan
> fornemme at jeg skal lære lidt bit-operationer :)
>
Du gør den fejl, at du tænker talrækken ud fra grundtallet 10.
Computeren regner ud fra grundtallet 2.

<< betyder faktisk at dividere med 2, mens >> betyder at gange med 2. Det
svarer til når du flytter decimalpunktum til venstre eller højre i
ti-tals systemet; flyt til venstre <=> dividere med grundtallet, og
flyt til højre <=> gange med grundtallet.

Det smarte ved en computer er så, at shift-operationen kun kræver en
instruktion, mens gange og dividere kræver flere operationer - afhænger
af tallets størrelse, og hvor mange bit din CPU kan håndterer per
operation.

--
Hilsen/Regards
Michael Rasmussen
http://keyserver.veridis.com:11371/pks/lookup?op=get&search=0xE3E80917


Kent Friis (27-08-2005)
Kommentar
Fra : Kent Friis


Dato : 27-08-05 14:39

Den Sat, 27 Aug 2005 14:36:18 +0200 skrev Morten Larsen:
>
> "Kent Friis" <nospam@nospam.invalid> skrev i en meddelelse
> news:43105620$0$18650$14726298@news.sunsite.dk...
>> Den Sat, 27 Aug 2005 13:53:24 +0200 skrev Morten Larsen:
>
>>> Jeg vil gerne have det samme resultat i C :) Så håber du kan hjælpe mig
>>> med
>>> det?
>>
>> Det svarede han faktisk også på, hvis du læser *hele* svaret.
>
> I må meget undskylde, men så kan jeg altså ikke se det :)

Det var heller ikke så stort

> Mogens gav 2 andre eksempler på hvordan det kan gøres.

Og midt imellem stod denne linie:

>>>>Hvor stor er en unsigned long på den anden platform ?

Det er lige præcis det der er problemet. Hvis den er 32 bits, kan
en signed kun indeholde 31 bits plus fortegnet, og en unsigned kan
indeholde alle 32 bits.

Når man så propper 32 bits ind i en signed long der kun kan indeholde
31, så ryger den sidste op og overskriver fortegnet. Bang, negative
tal.

Prøv at lave alle fem variable unsigned long, og se om ikke det løser
problemet, uanset hvilken metode du bruger.

>>> a = floor( addr / pow(256,3) );
>>> b = floor( (addr % (int)pow(256,3)) / pow(256,2) );
>>> c = floor( ( (addr % (int)pow(256,3)) % (int)pow(256,2) ) /
>>> pow(256,1) );
>>> d = floor( ( ( (addr % (int)pow(256,3)) % (int)pow(256,2) ) %
>>> (int)pow(256,1) ) / pow(256,0) );
>>>
>>> Ovenstående har du sikkert også en nemmere og bedre måde at gøre på?
>>
>> and (&), shift right (>>).
>
> Mange tak, men ville ønske jeg vidste hvordan jeg skulle bruge dem :)

a=addr>>24;
b=(addr>>16) & 255;
c=(addr>>8) & 255;
d=addr & 255;

> Jeg vil hverken kalde mig for matematiker eller pro programmør :)
> Jeg sad med problemet at skulle arbejde med ip ranges.
> Efter søgning på google fandt jeg den formel jeg brugte i mit første indlæg.

Bad luck. Den der har skrevet formlen må være matematiker og ikke
programmør

> Men kan fornemme at jeg skal lære lidt bit-operationer :)

Det gør den slags *meget* nemmere (og hurtigere, medmindre compileren
kan se "hov, han dividere med 263^3, det der det samme som >>24).

Mvh
Kent
--
Hard work may pay off in the long run, but laziness pays off right now.

Mogens Hansen (27-08-2005)
Kommentar
Fra : Mogens Hansen


Dato : 27-08-05 15:19


"Morten Larsen" <not@4u.com> wrote in message
news:43105e38$0$25947$edfadb0f@dread12.news.tele.dk...

[8<8<8<]
> Det jeg ikke forstår er hvorfor addr bliver lig med "-1062731519" i C.

Hvordan ser du at den har den værdi ?

Lidt mere præcist:
Du har i det program angivet at "addr" er af typen "unsigned long".
Hvordan kan en "unsigned" antage en negativ værdi ?

Bruger du f.eks. printf (i en eller anden variant) med forkert format
specifier eller en debugger der fejlfortolker "unsigned long"`?

Venlig hilsen

Mogens Hanen



Morten Larsen (27-08-2005)
Kommentar
Fra : Morten Larsen


Dato : 27-08-05 16:03


"Mogens Hansen" <mogens_h@dk-online.dk> skrev i en meddelelse
news:43107669$0$78284$157c6196@dreader1.cybercity.dk...
>
> "Morten Larsen" <not@4u.com> wrote in message
> news:43105e38$0$25947$edfadb0f@dread12.news.tele.dk...
>
> [8<8<8<]
>> Det jeg ikke forstår er hvorfor addr bliver lig med "-1062731519" i C.
>
> Hvordan ser du at den har den værdi ?

Se længere nede

> Lidt mere præcist:
> Du har i det program angivet at "addr" er af typen "unsigned long".
> Hvordan kan en "unsigned" antage en negativ værdi ?

Ja det aner jeg heller ikke, derfor jeg spørger her :)
Som jeg har forstået det:
unsigned = kun positive numre.
signed = positive og negative numre
Og udfra hvad Kent skrev, tolker jeg det sådan at unsigned kan holde en
større positiv værdi end signed da den første bit ikke skal bruges til at
indikere om tallet er positivt eller negativt.
Er det rigtigt forstået?

> Bruger du f.eks. printf (i en eller anden variant) med forkert format
> specifier eller en debugger der fejlfortolker "unsigned long"`?

Ja, i C testen bruger jeg printf("Resultat: %d", addr);
Og i min cpp test bruger jeg Form1->Caption ) (AnsiString)addr;
Jeg har lige været over og handle, på den tur tænkte jeg faktisk på at det
kunne være printf.

Jeg har lige ændret printf("Resultat: %d", addr) til
_i64toa(addr, str, 10);
printf(str);

Og nu virker det. Så forstår jeg meget bedre det har givet mig så mange
problemer.
Det andet gav nemlig ingen mening. Og vidste ikke dette var et problem med
printf.

Men i skal alle sammen have mange tak for hjælpen :)

//Morten



Mogens Hansen (27-08-2005)
Kommentar
Fra : Mogens Hansen


Dato : 27-08-05 16:14


"Morten Larsen" <not@4u.com> wrote in message
news:431080a3$0$37076$edfadb0f@dread12.news.tele.dk...
>
> "Mogens Hansen" <mogens_h@dk-online.dk> skrev i en meddelelse

[8<8<8<]
>> Bruger du f.eks. printf (i en eller anden variant) med forkert format
>> specifier eller en debugger der fejlfortolker "unsigned long"`?
>
> Ja, i C testen bruger jeg printf("Resultat: %d", addr);

Det var hvad jeg forestillede mig.

Hvad betyder "%d": signed decimal integer
printf familien er _ikke_ typesikker (det har gennem tiderne givet masser af
problemer). Den fortolker bitmønsteret på stakken i henhold til
formatstrengen - uanset hvad der måtte ligge der.
Det vil sige at når du skriver signed integer, så bliver det tolket som
sådan, og som Arne Valhøj skrev så har -1062731519L og 3232235777UL er samme
bit mønster.

Du skal skrive "%ul" i stedet når "addr" har typen "unsigned long".

Venlig hilsen

Mogens Hansen



Arne Vajhøj (27-08-2005)
Kommentar
Fra : Arne Vajhøj


Dato : 27-08-05 16:16

Morten Larsen wrote:
> Ja, i C testen bruger jeg printf("Resultat: %d", addr);
> Og i min cpp test bruger jeg Form1->Caption ) (AnsiString)addr;
> Jeg har lige været over og handle, på den tur tænkte jeg faktisk på at det
> kunne være printf.
>
> Jeg har lige ændret printf("Resultat: %d", addr) til
> _i64toa(addr, str, 10);
> printf(str);
>
> Og nu virker det. Så forstår jeg meget bedre det har givet mig så mange
> problemer.
> Det andet gav nemlig ingen mening. Og vidste ikke dette var et problem med
> printf.

printf bør virke hvis du erstatter %d med %lu

Arne

Mogens Hansen (27-08-2005)
Kommentar
Fra : Mogens Hansen


Dato : 27-08-05 13:30


"Morten Larsen" <not@4u.com> wrote in message
news:4310542a$0$37092$edfadb0f@dread12.news.tele.dk...

[8<8<8<]
> Men problemet er ikke i pow, tror snare det er * (gange) der driller.

Nej det er et "signed"/"unsigned" + overflow problem.

Programmet
int main()
{
unsigned long addr;
int a,b,c,d;
a = 192;
b = 168;
c = 1;
d = 1;
addr = (((unsigned) a) << 24) +
(((unsigned) b) << 16) +
(((unsigned) c) << 8) +
(((unsigned) d) << 0);
return 0;
}

vil give det rigtige på alle (fungerende) platforme hvis "unsigned long"
minimum er 32 bit.

>
> Min udregning: -1062731519
> Din nummer 1: -1062731519
> Dim nummer 2: -1062731519

Nej.
Som jeg skrev så giver de det rigtige resultat, når der er oversat som et C
program med C++Builder - jeg havde prøvet.

Oversætter du til en anden platform ?

>
> Men resultatet i cpp og andre sprog jeg har testet i, bliver resultatet
> ikke -1062731519 men 32322355777.

Prøv at lægge 1062731519 og 3232235777 sammen, så vil du se at det er 2^32.
Det er et vink med en vognstang.

Hvis du prøver at gemme resultatet i en 32 bit _signed_ integer så får du
netop det negative resultat.

> Jeg vil gerne have det samme resultat i C :) Så håber du kan hjælpe mig
> med det?

Det har, som jeg skrev, ikke noget med C vs. C++ at gøre.

[8<8<8<]
> Ovenstående har du sikkert også en nemmere og bedre måde at gøre på?

Ja - det har jeg allerede beskrevet.

Venlig hilsen

Mogens Hansen



Troels Thomsen (30-08-2005)
Kommentar
Fra : Troels Thomsen


Dato : 30-08-05 08:36

> unsigned long addr;
> int a,b,c,d;
> a = 192;
> b = 168;
> c = 1;
> d = 1;
> addr = (((unsigned) a) << 24) +
> (((unsigned) b) << 16) +
> (((unsigned) c) << 8) +
> (((unsigned) d) << 0);
> return 0;
> }
>
> vil give det rigtige på alle (fungerende) platforme hvis "unsigned long"
> minimum er 32 bit.
>

Er der ikke også et krav til int'erne ?
Har en char, skiftet op med 24, ikke udefineret værdi?

tpt




Mogens Hansen (30-08-2005)
Kommentar
Fra : Mogens Hansen


Dato : 30-08-05 09:39


"Troels Thomsen" <asdf@asdf.dk> wrote in message
news:43140c53$0$2312$edfadb0f@dread11.news.tele.dk...

[8<8<8<]
> Er der ikke også et krav til int'erne ?

Jo, de skal også være minimum 32 bit.
Det var sikkert bedre hvis a,b,c, og d var castet til "unsigned long",

> Har en char, skiftet op med 24, ikke udefineret værdi?

Typen af resultatet af en "char" skiftet 24 bit er "int" eller "unsigned
int" ud fra reglerne om "integral promotion".
Hvis "int" eller "unsigned int" er mindre end 32 bit giver det en udefineret
værdi.

Venlig hilsen

Mogens Hansen



Arne Vajhøj (27-08-2005)
Kommentar
Fra : Arne Vajhøj


Dato : 27-08-05 13:39

Morten Larsen wrote:
> Jeg har prøvet en del i C, for at få det til at virke.
> Men problemet er ikke i pow, tror snare det er * (gange) der driller.
>
> Min udregning: -1062731519
> Din nummer 1: -1062731519
> Dim nummer 2: -1062731519
>
> Men resultatet i cpp og andre sprog jeg har testet i, bliver resultatet
> ikke -1062731519 men 32322355777.
> Jeg vil gerne have det samme resultat i C :) Så håber du kan hjælpe mig med
> det?

Du har samme resultat i C !

Du har bare glemt unsigned keyworded.

-1062731519L og 3232235777UL er samme bit mønster.

Arne

Søg
Reklame
Statistik
Spørgsmål : 177429
Tips : 31962
Nyheder : 719565
Indlæg : 6407948
Brugere : 218878

Månedens bedste
Årets bedste
Sidste års bedste