Sida 1 av 1

Problem med stora tal i C++

Postat: 02 jul 2007, 22:57
av Emil.s
Betrakta följande kod:

Kod: Markera allt

emil@emils-macbook.local: ~/Documents/Program $ cat Bas.cpp
#include <iostream>
using namespace std;
int main()
{
        long double stort_tal = 100000000000000000000.0;
        cout.precision(25);
        cout << stort_tal << endl;
        stort_tal -= 1;
        cout << stort_tal <<endl;
}

emil@emils-macbook.local: ~/Documents/Program $ g++ -Wall Bas.cpp 
emil@emils-macbook.local: ~/Documents/Program $ ./a.out 
100000000000000000000
100000000000000000000
Tar man bort en nolla, blir det som ni erfarna säkert redan räknat ut:

Kod: Markera allt

emil@emils-macbook.local: ~/Documents/Program $ ./a.out 
10000000000000000000
9999999999999999999
Varför? Borde inte en 128bitars "long double" palla mer? :P
2^128 = 340282366920938463463374607431768211456 enligt mina beräkningar.

SV: Problem med stora tal i C++

Postat: 02 jul 2007, 23:05
av Lars
sizeof(long double) ger 12 på min 32-bitarsmaskin, d.v.s enbart 96 bitar.

Edit: kolla även LDBL_DIG i float.h, ger värdet 18 här.

SV: Problem med stora tal i C++

Postat: 02 jul 2007, 23:32
av Emil.s
Lars skrev: sizeof(long double) ger 12 på min 32-bitarsmaskin, d.v.s enbart 96 bitar.

Edit: kolla även LDBL_DIG i float.h, ger värdet 18 här.
Att det är 128 har jag koll på:

Kod: Markera allt

emil@emils-macbook.local: ~/Documents/Program $ cat Bas.cpp
#include <iostream>
using namespace std;
int main()
{
        cout << sizeof(long double) << endl;
}

emil@emils-macbook.local: ~/Documents/Program $ g++ -Wall Bas.cpp 
emil@emils-macbook.local: ~/Documents/Program $ ./a.out 
16
Tror att det är den här filen du vill åt:

Kod: Markera allt

emil@emils-macbook.local: ~/Documents/Program $ cat /usr/include/float.h | grep LDBL_DIG
#ifndef __LDBL_DIG__  
#define __LDBL_DIG__ 15 
#undef LDBL_DIG
#define LDBL_DIG        __LDBL_DIG__

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 00:33
av Lars
Aha, macbook, PowerPC alltså? Men det verkar ju konstigt att LDBL_DIG för dina 128-bitars flyttal är mindre än för mina 96-bitars.

Antalet värdesiffror bestäms inte av längden på hela flyttalet, utan på längden av mantissan. Hos mig är mantissan (LDBL_MANT_DIG) 64 bitar. 2^64 = 1.8e19, det garanterar 18 värdesiffror (orkar inte förstå varför det inte är 19 just nu...). IEEE 754-formatet beskrivs här, PowerPC har kanske något eget, men det är förmodligen liknande.

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 01:07
av Emil.s
Lars skrev: Aha, macbook, PowerPC alltså? Men det verkar ju konstigt att LDBL_DIG för dina 128-bitars flyttal är mindre än för mina 96-bitars.

Antalet värdesiffror bestäms inte av längden på hela flyttalet, utan på längden av mantissan. Hos mig är mantissan (LDBL_MANT_DIG) 64 bitar. 2^64 = 1.8e19, det garanterar 18 värdesiffror (orkar inte förstå varför det inte är 19 just nu...). IEEE 754-formatet beskrivs här, PowerPC har kanske något eget, men det är förmodligen liknande.
MacBook är nya Intel Macarna. Powerbook var med PowerPC. I den här snurrar en Intel Core 2 Duo.

Vad LDBL_DIG gör har jag ingen aning om. Är en riktig nybörjare innom programmering. Håller på att lära mig. :)

btw:

Kod: Markera allt

emil@emils-macbook.local: ~ $ g++ -v
Using built-in specs.
Target: i686-apple-darwin8
Configured with: /private/var/tmp/gcc/gcc-5367.obj~1/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib --build=powerpc-apple-darwin8 --with-arch=nocona --with-tune=generic --program-prefix= --host=i686-apple-darwin8 --target=i686-apple-darwin8
Thread model: posix
gcc version 4.0.1 (Apple Computer, Inc. build 5367)

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 05:39
av Okänd
Läs mer om hur flyttal är lagrade i datorn http://sv.wikipedia.org/wiki/Flyttal samt jag tror det är datatypen long long som du söker efter...

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 12:20
av Emil.s
gasol skrev: Läs mer om hur flyttal är lagrade i datorn http://sv.wikipedia.org/wiki/Flyttal samt jag tror det är datatypen long long som du söker efter...
Aha! Nu börjar jag att hänga med lite. Läste på mer i boken jag har om Flyttal också. Så nu vet jag hur det funkar. :)

Men hur gör de då när de räknar ut sina jätteberäkningar i superdator cluster? Har de något eget specialspråk då eller?

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 15:48
av Konservburk
Emil.s skrev: Men hur gör de då när de räknar ut sina jätteberäkningar i superdator cluster? Har de något eget specialspråk då eller?
Jag vet inte exakt vad de använder. Men det finns färdiga
bibliotek som hanterar stora tal, t.ex. GMP.

http://gmplib.org/

Du kan använda det själv, utan superdator. :)

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 16:17
av Emil.s
DrKonservburk skrev:
Emil.s skrev: Men hur gör de då när de räknar ut sina jätteberäkningar i superdator cluster? Har de något eget specialspråk då eller?
Jag vet inte exakt vad de använder. Men det finns färdiga
bibliotek som hanterar stora tal, t.ex. GMP.

http://gmplib.org/

Du kan använda det själv, utan superdator. :)

WOW! Det där ska jag ta en titt på. Inte för att jag behöver, men det kan ju vara kul att kunna.  8)

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 16:29
av Okänd
Du kan ju själv skapa en egna datatyper (är dock lite bökigt med flyttal) te.x. en 20 bytes integer (heltal)

Sedan så överlagrar du + - / % * osv... på detta sätt så kan du ju lagra väldigt stora tal!

Men när du utför dina operationer (+ - / * %) så kommer dessa att ta längre tid än de inbyggda typerna, eftersom CPUn är byggd för att göra dessa snabbt (samt att du får massa overhead vid funktions anrop).
I din CPU har du en så kallade FPU floating point unit som gör dina flytalsoperationer samt en ALU (Arithmetic logic unit) som gör dina heltals operationer.
När du skapar egna större datatyper så kommer dessa två enheter att utnyttjas flera gånger på samma tal, detta medför att det går långsammare att räkna ut sånna tal. Om jag inte minns fel så tar ALU:n och FPU:n i vanliga fall tal med samma word-size som CPU:n

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 17:12
av Emil.s
gasol skrev: Du kan ju själv skapa en egna datatyper (är dock lite bökigt med flyttal) te.x. en 20 bytes integer (heltal)

Sedan så överlagrar du + - / % * osv... på detta sätt så kan du ju lagra väldigt stora tal!

Men när du utför dina operationer (+ - / * %) så kommer dessa att ta längre tid än de inbyggda typerna, eftersom CPUn är byggd för att göra dessa snabbt (samt att du får massa overhead vid funktions anrop).
I din CPU har du en så kallade FPU floating point unit som gör dina flytalsoperationer samt en ALU (Arithmetic logic unit) som gör dina heltals operationer.
När du skapar egna större datatyper så kommer dessa två enheter att utnyttjas flera gånger på samma tal, detta medför att det går långsammare att räkna ut sånna tal. Om jag inte minns fel så tar ALU:n och FPU:n i vanliga fall tal med samma word-size som CPU:n
Ok,hur det funkar med egna datatyper har jag dock ingen aning om. :P Men du menar alltså att man har nyp en "int" på kanske 4, och sen multiplcerar man den med en typ "long double" på 1 000 000 000 000 000, för att få ett större tal?

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 17:44
av Okänd
nope tänkte mer nåt i stil med att typ allokerar en array med 16st char eller dylikt, sedan implementerar du + - / * %  | & ^ operationerna.


(alla unsigned för enkelhetens skulle ) te.x. i en short så kan du 16 bitar, det är 2 bytes.
2^16 = 65,536 = SHORT_MAX
i en vanlig int så har du 4 bytes, eller 32 bitar
2^32 = 4,294,967,296 = INT_MAX

osv...

Om du tar te.x. en char array med 16 element. så får du 16 bytes. Dvs
2^(16*8 ) = 2^128 = (djävligt stort tal)

Problemet blir ju när du ska lägga ihop tal (även om vi helt bortser från flytal)

Såhär lägger man ju som bekant ihop tal binärt:

Kod: Markera allt

  11
0000 1000
0001 1001
---------
0010 0001 
Fast man kan ju få overflow!

Kod: Markera allt

1 1000 1000
X 1100 1001
-----------
X 0101 0001

Som du ser i additionen ovan så tappar man den sista 1:an som skulle tas med. Detta innebär att man ha fått ett så kallat overflow. Denna sista 1:a måste man räkna med i nästa byte (vi har 16) st, ja fast inte i den sista byten så klart!

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 17:55
av Emil.s
gasol skrev: nope tänkte mer nåt i stil med att typ allokerar en array med 16st char eller dylikt, sedan implementerar du + - / * %  | & ^ operationerna.


(alla unsigned för enkelhetens skulle ) te.x. i en short så kan du 16 bitar, det är 2 bytes.
2^16 = 65,536 = SHORT_MAX
i en vanlig int så har du 4 bytes, eller 32 bitar
2^32 = 4,294,967,296 = INT_MAX

osv...

Om du tar te.x. en char array med 16 element. så får du 16 bytes. Dvs
2^(16*8 ) = 2^128 = (djävligt stort tal)

Problemet blir ju när du ska lägga ihop tal (även om vi helt bortser från flytal)

Såhär lägger man ju som bekant ihop tal binärt:

Kod: Markera allt

  11
0000 1000
0001 1001
---------
0010 0001 
Fast man kan ju få overflow!

Kod: Markera allt

1 1000 1000
X 1100 1001
-----------
X 0101 0001

Som du ser i additionen ovan så tappar man den sista 1:an som skulle tas med. Detta innebär att man ha fått ett så kallat overflow. Denna sista 1:a måste man räkna med i nästa byte (vi har 16) st, ja fast inte i den sista byten så klart!


Aha! Då är jag med. :)
Iof så är det väl inte så viktigt, stötte på problemet när jag moddade lite exempelkod i en övning.  8)

Tack alla! :)

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 18:11
av Okänd
Emil.s skrev:
gasol skrev: nope tänkte mer nåt i stil med att typ allokerar en array med 16st char eller dylikt, sedan implementerar du + - / * %  | & ^ operationerna.


(alla unsigned för enkelhetens skulle ) te.x. i en short så kan du 16 bitar, det är 2 bytes.
2^16 = 65,536 = SHORT_MAX
i en vanlig int så har du 4 bytes, eller 32 bitar
2^32 = 4,294,967,296 = INT_MAX

osv...

Om du tar te.x. en char array med 16 element. så får du 16 bytes. Dvs
2^(16*8 ) = 2^128 = (djävligt stort tal)

Problemet blir ju när du ska lägga ihop tal (även om vi helt bortser från flytal)

Såhär lägger man ju som bekant ihop tal binärt:

Kod: Markera allt

  11
0000 1000
0001 1001
---------
0010 0001 
Fast man kan ju få overflow!

Kod: Markera allt

1 1000 1000
X 1100 1001
-----------
X 0101 0001

Som du ser i additionen ovan så tappar man den sista 1:an som skulle tas med. Detta innebär att man ha fått ett så kallat overflow. Denna sista 1:a måste man räkna med i nästa byte (vi har 16) st, ja fast inte i den sista byten så klart!


Aha! Då är jag med. :)
Iof så är det väl inte så viktigt, stötte på problemet när jag moddade lite exempelkod i en övning.  8)

Tack alla! :)
hehe näe så stora tal behöver man sällan ^_^ men det är smidigt att veta vad som händer vid overflow (när man använder mindre datatyper) samt skillnaderna på signed och unsigned.

SV: Problem med stora tal i C++

Postat: 03 jul 2007, 19:50
av Barre
gasol skrev: hehe näe så stora tal behöver man sällan ^_^ men det är smidigt att veta vad som händer vid overflow ...
jag förstörde en märkmaskin (ca pris 800.000:-) när jag programmerade en styrkrets för att pyttsa ut lösningsmedel, fungerade hela vintern till sommaren kom och registret som skötte temperatur variabeln visade gå på en overflow....
gissa om jag skämdes när jag upptäckte varför märkmaskinen badade i lösningmedel en dag ;D

det har gått 10-15 år sen, men det sitter i fortfarande...

SV: Problem med stora tal i C++

Postat: 04 jul 2007, 16:59
av Okänd
Barre skrev:
gasol skrev: hehe näe så stora tal behöver man sällan ^_^ men det är smidigt att veta vad som händer vid overflow ...
jag förstörde en märkmaskin (ca pris 800.000:-) när jag programmerade en styrkrets för att pyttsa ut lösningsmedel, fungerade hela vintern till sommaren kom och registret som skötte temperatur variabeln visade gå på en overflow....
gissa om jag skämdes när jag upptäckte varför märkmaskinen badade i lösningmedel en dag ;D

det har gått 10-15 år sen, men det sitter i fortfarande...
haha underbar historia!