Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Developing U++ » U++ Developers corner » Decimal
Decimal [message #17172] Fri, 01 August 2008 10:10 Go to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Well, it looks like Firebird seems to force us to add Decimal support.

I was googling a bit and found there two relevant topics:

http://docs.python.org/lib/module-decimal.html
http://www.yoda.arachsys.com/csharp/decimal.html

It looks like there are some standards -> I would recommend to follow them here.

Mirek

[Updated on: Fri, 01 August 2008 10:45]

Report message to a moderator

Re: Decimal [message #17173 is a reply to message #17172] Fri, 01 August 2008 10:31 Go to previous messageGo to next message
masu is currently offline  masu
Messages: 378
Registered: February 2006
Senior Member
There is also a WP article on DFP:

http://en.wikipedia.org/wiki/Decimal_floating_point

It also contains links to the actual IEEE standard.

Matthias
Re: Decimal [message #17176 is a reply to message #17173] Fri, 01 August 2008 11:18 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Well, completely opposite idea... Smile

Maybe we could use int128 (supported by both MSC and GCC) and sort of fixed point, only removing last 4 or 5 bits of number to specify the precission (as number of significant places).

That would give as ability to represent 10^20 numbers with up to 10^-16 precision (if I have computed numbers well Smile.

Mirek
Re: Decimal [message #17209 is a reply to message #17176] Sat, 02 August 2008 13:30 Go to previous messageGo to next message
aldeacity is currently offline  aldeacity
Messages: 18
Registered: July 2008
Location: Spain
Promising Member
Hello,
perhaps int128 would be a very good idea Smile. But, sorry if I make a mistake, but, until now, how does Oracle for Upp manage number(x,y) data?

Juan.
Re: Decimal [message #17210 is a reply to message #17209] Sat, 02 August 2008 13:54 Go to previous messageGo to next message
unodgs is currently offline  unodgs
Messages: 1366
Registered: November 2005
Location: Poland
Ultimate Contributor

aldeacity wrote on Sat, 02 August 2008 07:30

Hello,
perhaps int128 would be a very good idea Smile. But, sorry if I make a mistake, but, until now, how does Oracle for Upp manage number(x,y) data?

Juan.

All decimal types in other databases are converted to double. I will try to implement int128 based decimal.
Re: Decimal [message #17211 is a reply to message #17210] Sat, 02 August 2008 14:21 Go to previous message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Well, here is something to start with Smile

#include <Core/Core.h>

using namespace Upp;

double pow2(int x)
{
	double b = 1;
	while(x--)
		b *= 2;
	return b;
}

typedef __int128_t int128;

#define I128_10_17 (int128)I64(1000000000) * (int128)I64(100000000)

struct Decimal {
	int128 data;
	
	static int128 e10[38];
	
public:
	void Add(const Decimal& b) {
		byte sa = data & 15;
		byte sb = b.data & 15;
		data = (~(int128)15 & data) + (~(int128)15 & b.data) | max(sa, sb);
	}
	void Mul(const Decimal& b) {
		byte sa = data & 15;
		byte sb = b.data & 15;
		data = (((~(int128)15 & data) * (~(int128)15 & b.data)) / I128_10_17) | max(sa + sb, 16);
	}
	
	String ToString() const;
	const char *Scan(const char *s);
	
	Decimal();
};

int128 Decimal::e10[38];

Decimal::Decimal()
{
	static bool init;
	if(!init) {
		int128 q = 1;
		for(int i = 0; i < 38; i++) {
			e10[i] = q;
			q = q * 10;
		}
	}
	data = 0;
}

String Format128(int128 a)
{
	RTIMING("Format128");

	if(a < 0)
		a = -a;
	char b[50];
	char *p = b + 50;
	do {
		*--p = a % 10 + '0';
		a = a / 10;
	}
	while(a);
	return String(p, b + 50);
}

const char *Decimal::Scan(const char *s)
{
	while(*s == ' ')
		s++;
	bool neg = false;
	if(*s == '-') {
		neg = true;
		s++;
	}
	while(*s == ' ')
		s++;
	if(!IsDigit(*s))
		return NULL;
	data = 0;
	while(IsDigit(*s))
		data = *s++ - '0' + 10 * data;
	int digits = 0;
	if(*s == '.') {
		s++;
		while(IsDigit(*s) && digits < 16) {
			data = *s++ - '0' + 10 * data;
			digits++;
		}
		while(IsDigit(*s)) s++;
	}
	data *= e10[16 - digits];
	if(neg)
		data = -data;
	data = (data & ~(int64)15 & data) | digits;
	return s;
}

String Decimal::ToString() const
{
	int digits = data & 15;
	String x = Format128(~(int64)15 & data);
	int n = x.GetLength();
	if(n <= 16)
		return "0." + x.Mid(0, digits);
	return x.Mid(0, n - 16) + "." + x.Mid(n - 16, digits);
}

Decimal Dec(const char *s)
{
	Decimal d;
	d.Scan(s);
	return d;
}

inline Decimal operator+(const Decimal& a, const Decimal& b)
{
	Decimal r = a;
	r.Add(b);
	return r;
}

inline Decimal operator*(const Decimal& a, const Decimal& b)
{
	Decimal r = a;
	r.Mul(b);
	return r;
}

CONSOLE_APP_MAIN
{
	DUMP(Dec("1.20"));
	DUMP(Dec("1.20") + Dec("2"));	
	DUMP(Dec("1.02") + Dec("1.005"));
	DUMP(Dec("1.02") * Dec("1"));
	DUMP(Dec("1.02") * Dec("0.50"));
	DUMP(Dec("1.02") * Dec("1.005"));
	return;
	
	RDUMP(Format128(I128_10_17));

	int64 x = I64(0x1234123412341234);
	DUMP(Format64Hex(x & ~(int64)15));
	Decimal a;
	Decimal b;
	a.Add(b);
	for(int i = 0; i < 128; i++) {
		LOG(i << ' ' << pow2(i));
	}
}



Conversions and + work, * not yet... You will need to adjust typedef for MSC.

Mirek
Previous Topic: Assist++ future
Next Topic: Choosing svn configuration
Goto Forum:
  


Current Time: Thu Apr 25 21:15:24 CEST 2024

Total time taken to generate the page: 3.11985 seconds