very very large integer to double

I've almost completed making a class named 'luint' to hold very large unsigned integers. It contains a data member 'std::vector<unsigned> a'. All features seem to work correctly except converting the number to a double.

Here is the shortened version of the class

luint.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include<vector>
#include<cstring>
#include<string>
#include<cmath>
#include"eku\bytes.h"
#include"eku\hexconv.h"

/*
Luint - Large Unsigned int
This data type uses a std::vector to store ints which 
concatenate bitwise to make a large unsigned int.
The smallest bits are stored in a[0], larger bits in a[1]
and so on. The size of the luint is extensible.
*/

namespace eku
{

	typedef unsigned __int32 styp;
	typedef unsigned __int64 btyp;
	const static unsigned ssize=sizeof(styp);
	const static unsigned bsize=sizeof(btyp);
	const static unsigned sbits=ssize*CHAR_BIT;
	const static unsigned bbits=ssize*CHAR_BIT;

	class luint
	{public:

//data-members--------------------------------------------------------------------

		std::vector<styp> a;
		bool sign;	//+ve sign is true and -ve sign is false.
		//As luint is unsigned, -ve sign means error
		//-ve sign can be encountered while using operator- or operator--

//Conversion-to-double------------------------------------------------------------

		unsigned exponent()const;
		//gets integral part of logarithm of *this to the base 2

		template<class dtyp>
		//dtyp can be double, float, long double, etc.
		dtyp signif(int prec=4)const;
		
		template<class dtyp>
		//dtyp can be double, float, long double, etc.
		dtyp as_double(int prec=4)const
		{return ldexp(signif<dtyp>(prec),exponent());}
	};

	template<class dtyp>
	//dtyp can be double, float, long double, etc.
	dtyp luint::signif(int prec/*=4*/)const
	{
		int i,j;dtyp d=1;
		if(a.size()==0)return 0;
		for(i=int(a.size())-1,j=0;i>=0 && j<prec;--i,++j)
		{d*=dtyp(a[i])*ldexp(double(1),(-j)*sbits);}
		return frexp(d,&i);
	}

	unsigned luint::exponent()const
	//gets integral part of logarithm of *this to the base 2
	{
		if(a.size()==0)return 0;
		styp v=a.back();
		unsigned exp=0;
		while(v){exp++;v>>=1;}
		return exp+(a.size()-1)*sbits;
	}
}

main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<cmath>
#include<iostream>
#include<iomanip>
#include<eku\luint.h>

using namespace std;
using namespace eku;

int main()
{
	luint big;
	double d,s;
	int i,e;
	cout<<"Enter a luint ";
	cin>>big;
	cout<<"Enter as double ";
	cin>>d;	//You are supposed to enter the same number as before
	s=frexp(d,&e);
	cout<<big<<endl;
	cout<<setprecision(15);
	cout<<"my sig = "<<big.signif<double>()<<endl;
	cout<<"my exp = "<<big.exponent()<<endl;
	cout<<"my double = "<<big.as_double<double>()<<endl;
	cout<<"\nsig = "<<s<<endl;
	cout<<"exp = "<<e<<endl;
	cout<<"double = "<<d<<endl;
	return 0;
}

The program displays the exponent correctly but doesn't display the significand correctly if the number entered is larger than the range of btyp styp.

For testing, here is the full code:
bytes.h: http://www.dropbox.com/s/yefjoh5bt0ku98d/bytes.h
hexconv.h: http://www.dropbox.com/s/qrefbjxaogwvy2g/hexconv.h
luint.h: http://www.dropbox.com/s/p6o4pdgr33lo3hh/luint.h
luint.cpp: http://www.dropbox.com/s/vm28ydep8zp8v0h/luint.cpp

(Edit: Add luint.cpp and main.cpp to project)
Last edited on
My output:
Enter a luint 112233445566778899
Enter as double 112233445566778899
112233445566778899
my sig = 0.577547528811055
my exp = 57
my double = 8.3233370737351e+016

sig = 0.778775971257826
exp = 57
double = 1.12233445566779e+017
Press any key to continue . . .
I figured it out myself:
in luint::signif(int), I used d*= instead of d+=.

1
2
3
4
5
6
7
8
9
10
template<class dtyp>
	//dtyp can be double, float, long double, etc.
	dtyp luint::signif(int prec/*=4*/)const
	{
		int i,j;dtyp d=0;
		if(a.size()==0)return 0;
		for(i=int(a.size())-1,j=0;i>=0 && j<prec;--i,++j)
		{d+=dtyp(a[i])*ldexp(double(1),(-j)*sbits);}
		return frexp(d,&i);
	}

If someone wants to copy the full code, do it quick as I will remove these links after a few days.
Last edited on
Can you explain how you did that? Does it support arithmetic? What is the advantage of using namespace instead of a class?
@Smac89 He is using a class.

@eklavya sharma 2
Have you tested with numbers larger than 112233445566778899, which will fit into an unsigned long long. Big num classes are usually written with the number stored as a string.
I thought that storing it as a string would be less efficient.

For eg. if I have 2 numbers which take 32 bytes each, they will fit in 8 elements each if I use ints and 32 elements each if I use char. Adding the numbers would take 8 iterations if I use int and 32 iterations if I use char. As the no. of iterations are lower with an int, storing it as ints would be more efficient.

I'm about to make major changes to the above files. I'm also adding new files. As these files are synced to my Dropbox, you wouldn't be able to see the previous versions. These files will not work if you download them now.

Smac89:
Does it support arithmetic?

Yes it does. But I haven't written the full code. You can see my full code by visiting the links I have provided.
Last edited on
Topic archived. No new replies allowed.