Problem med stora tal i C++

Här diskuteras programmering och utveckling
Emil.s
Inlägg: 6633
Blev medlem: 12 dec 2006, 23:20
OS: Ubuntu
Ort: /Dalarna/Hedemora/
Kontakt:

Problem med stora tal i C++

Inlägg 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.
Home sweet ~/ = http://sandnabba.se
Lars
Inlägg: 6191
Blev medlem: 14 jan 2007, 19:31
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Ort: Stockholm

SV: Problem med stora tal i C++

Inlägg 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.
Senast redigerad av 1 Lars, redigerad totalt 2 gånger.
Emil.s
Inlägg: 6633
Blev medlem: 12 dec 2006, 23:20
OS: Ubuntu
Ort: /Dalarna/Hedemora/
Kontakt:

SV: Problem med stora tal i C++

Inlägg 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__
Home sweet ~/ = http://sandnabba.se
Lars
Inlägg: 6191
Blev medlem: 14 jan 2007, 19:31
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Ort: Stockholm

SV: Problem med stora tal i C++

Inlägg 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.
Emil.s
Inlägg: 6633
Blev medlem: 12 dec 2006, 23:20
OS: Ubuntu
Ort: /Dalarna/Hedemora/
Kontakt:

SV: Problem med stora tal i C++

Inlägg 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)
Home sweet ~/ = http://sandnabba.se
Okänd
Inlägg: 30172
Blev medlem: 03 mar 2008, 01:30
OS: Ubuntu

SV: Problem med stora tal i C++

Inlägg 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...
Senast redigerad av 1 gasol, redigerad totalt 3 gånger.
Emil.s
Inlägg: 6633
Blev medlem: 12 dec 2006, 23:20
OS: Ubuntu
Ort: /Dalarna/Hedemora/
Kontakt:

SV: Problem med stora tal i C++

Inlägg 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?
Home sweet ~/ = http://sandnabba.se
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

SV: Problem med stora tal i C++

Inlägg 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. :)
Emil.s
Inlägg: 6633
Blev medlem: 12 dec 2006, 23:20
OS: Ubuntu
Ort: /Dalarna/Hedemora/
Kontakt:

SV: Problem med stora tal i C++

Inlägg 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)
Home sweet ~/ = http://sandnabba.se
Okänd
Inlägg: 30172
Blev medlem: 03 mar 2008, 01:30
OS: Ubuntu

SV: Problem med stora tal i C++

Inlägg 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
Emil.s
Inlägg: 6633
Blev medlem: 12 dec 2006, 23:20
OS: Ubuntu
Ort: /Dalarna/Hedemora/
Kontakt:

SV: Problem med stora tal i C++

Inlägg 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?
Home sweet ~/ = http://sandnabba.se
Okänd
Inlägg: 30172
Blev medlem: 03 mar 2008, 01:30
OS: Ubuntu

SV: Problem med stora tal i C++

Inlägg 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!
Senast redigerad av 1 gasol, redigerad totalt 3 gånger.
Emil.s
Inlägg: 6633
Blev medlem: 12 dec 2006, 23:20
OS: Ubuntu
Ort: /Dalarna/Hedemora/
Kontakt:

SV: Problem med stora tal i C++

Inlägg 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! :)
Home sweet ~/ = http://sandnabba.se
Okänd
Inlägg: 30172
Blev medlem: 03 mar 2008, 01:30
OS: Ubuntu

SV: Problem med stora tal i C++

Inlägg 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.
Användarvisningsbild
Barre
Inlägg: 2298
Blev medlem: 13 dec 2006, 10:23
OS: Ubuntu
Ort: Stockholm
Kontakt:

SV: Problem med stora tal i C++

Inlägg 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...
________________________________________________________________
twitter @ BarreGargamel
blogg @ Gargamel.NU
Okänd
Inlägg: 30172
Blev medlem: 03 mar 2008, 01:30
OS: Ubuntu

SV: Problem med stora tal i C++

Inlägg 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!
Skriv svar

Återgå till "Programmering och webbdesign"