/* Funktionen für andere JavaScripts
 * Erstellt: 9.11.2006
 * Zuletzt Geändert: 6.5.2007
 * Author:	 Gerd Katzenbeisser
 *
 * History
 * =============================================================================
 * Stand 6.5.2007:
 * -----------------------------------------------------------------------------
 * String-Methoden eingefügt für Safari
 * rational.toDecimal gibt gegebenenfalls NaN zurück
 * =============================================================================
 * Stand 5.1.2007:
 * -----------------------------------------------------------------------------
 * Debugging von Rational.cancel()
 * Debugging von Integer.compare()
 * GlobalNumber verwendet Rational
 * =============================================================================
 * Stand 30.12.2006:
 * -----------------------------------------------------------------------------
 * Dezimalausgabe von Rational
 * =============================================================================
 * Stand 1.12.2006:
 * -----------------------------------------------------------------------------
 * Rational 0.8 implementiert. Alle Grundrechenarten sind darin möglich und es
 * wird das Ergebnis automatisch gekürzt.
 * Was fehlt ist Potenzieren, und Die Möglichkeit das Ergebnis als Dezimalzahl
 * auszugeben. Das Skript wird für sehr große und kleine Zahlen auch extrem
 * langsam. Bei Finanzmathematischen Berechnungen sollte das aber kein Problem
 * sein.
 * Natural 1.6
 * Nur kleine Änderungen bei der Initialisierung der Zahlen
 * Integer 2.5
 * Implementierung vieler Mathematischer Funktionen basierend auf Natural.
 * Änderung bei der Initialisierung der Zahlen.
 * =============================================================================
 * Stand 30.11.2006:
 * -----------------------------------------------------------------------------
 * Natural V 1.5 (pow, ggT, kgV, divide)
 * Auch einige Bugs wurden entfernt
 * =============================================================================
 * Stand 29.11.2006:
 * -----------------------------------------------------------------------------
 * Integer V 2.0
 * Natural V 1.0
 * Basisfunktionen wurden in Natural ausgelagert. Integer hat jetzt eine Natural
 * Number als Value.
 * =============================================================================
 * Stand 28.11.2006:
 * -----------------------------------------------------------------------------
 * Cookie-Funktionen wieder eingefügt.
 * Bug: GlobalNumber() Wird eine Nachkommastelle die 9 ist aufgerundet wird auf 
 * 10 gerundet und diese Zahl auch ausgegeben.
 * Bug: GlobalNumber() Das Objekt kann nicht mit Exponentialwerten umgehen zb:
 * 5e-204
 * Integer V 1.0 
 * Rational-Klasse angefangen
 * =============================================================================
 * Stand 27.11.2006:
 * -----------------------------------------------------------------------------
 * Bugfix: NaN-Werte wurden mit NaN,0...0 bei toGermanString oder
 * toEnglishSring dargestellt.
 * =============================================================================
 * Stand 10.11.2006:
 * -----------------------------------------------------------------------------
 * Cookie-Funktionen verschoben, da es zu Ladezeit-problemen der Scripts
 * gekommen ist. Eine Lösung für dieses Problem ist zu finden um die Funktionen
 * ordentlich auszulagern.
 * =============================================================================
 * Stand 9.11.2006:
 * -----------------------------------------------------------------------------
 * Global Number<
 * Cookie-Funktionen
 */

// NumbersTestsuite();
function NumbersTestsuite() {
	
	// Test Natural Numbers
//	var Zero = new Rational("0")
	var A = new Rational("5");
	var B = new Rational("4");
	document.write( new GlobalNumber(A.divide(B)).toGermanString(0,1));
	
/*	var C = A.multiply(B);
	document.write(C.toString());
	document.write("<br>");
	var Teststring =  "" + (11111111 & 00000001);
	var Test = new Natural (3528);
	var bin0 = new Natural (3780);
	var bin1 = 1000000000000000000000000000000000000000000000000000000;
	var bin2 = bin0.divide(0);
	document.write(bin2 + "<br>");
	var bin3 = bin0.ggT(Test);
	document.write(bin3 + "<br>");
	var bin3 = bin0.kgV(Test);
	document.write(bin3 + "<br>");
	*/
	
	//document.write(Teststring.charCodeAt(0));
	
}

function Natural(Arg0) {
	// V 1.6
	// Verbesserungsansätze: Repräsentieren der Zahlen als Binary
	// Einbau des "Schnellen Potenzierens" (Square & Multiply)
		
	var Value;
	
	Arg0 = "" + Arg0;
	
	if (Arg0.match(/^\d+$/))
		Value = Arg0.match(/^0+$/) ? "0" : Arg0.replace(/^0+/, "");
	else
		Value = "NaN";

	this.isNaN = function() {
		return Value == "NaN" ? true:false;
	}
	
	this.isEven = function() {
		if (this.isNaN())
			return null;
		
		return Value.substr(Value.length - 1) % 2 == 0 ? true:false;
	}
	
	this.isOdd = function() {
		if (this.isNaN())
			return null;
		
		return !this.isEven();
	}
	
	this.mod = function (Arg0) {
		// Beide Objekte Naturals, oder als Natural darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Natural(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Number("NaN");
			
		return this.dist(this.divide(Arg0, true).multiply(Arg0));
	}
	
	this.divide = function(Arg0, Arg1) {
		// Wenn Arg1 gesetzt, wird das Ergebnis ausgegeben, auch wenn
		// keine Exakte Zahl gefunden wurde. Es wird das abgerundete
		// Ergebnis zurückgegeben.
		var ReturnRounded = typeof(Arg1) != "boolean" ? false : Arg1;
		
		// Beide Objekte Naturals, oder als Natural darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Natural(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Number("NaN");

		// Ist der Divisor größer als der Dividend?
		if (Arg0.compare(this) == 1)
			return ReturnRounded ? new Natural(0) : new Natural("NaN");

		var Dividend = Value;
		var Divisor = Arg0.getValue();
		var Result = "";
		var i = Divisor.length-1;
		var Remainer = Dividend.substring(0,i);
		
		while (i < Dividend.length) {
			var DividendPart = Remainer;
			
			while (i < Dividend.length) {
				DividendPart +=  Dividend.substr(i,1);
				if (new Natural(DividendPart).compare(Divisor) != -1)
					break;
				Result += "0";
				i++;
			}
			
			if (i >= Dividend.length)
				break;
			
			// Suchen nach der passenden Ergebnisstelle
			var Subtrahend;
			for (var j = 9; j >= 0; j--) {
				Subtrahend = Arg0.multiply(j);
				if (Subtrahend.compare(DividendPart) <= 0)
				{
					Result += "" + j;
					break;
				}
			}
			
			Remainer = Subtrahend.dist(DividendPart).toString().replace(/^0+/, "");

			i++;
		}
		
		return 	Remainer != "" && !ReturnRounded ? new Natural ("NaN") : new Natural (Result);
	}
	
	
	this.kgV = function(Arg0) {
		// Beide Objekte Naturals, oder als Natural darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Natural(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Number("NaN");
		
		return this.multiply(Arg0).divide(this.ggT(Arg0));
	}
	
	this.ggT = function (Arg0) {
		// Nach dem Steinschen Algorithmus
		
		// Beide Objekte Naturals, oder als Natural darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Natural(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Number("NaN");
			
		var a = new Natural(this);
		var b = new Natural(Arg0);
		var k = 0;
		while (a.isEven() && b.isEven())
		{
			a = a.divide(2, true);
			b = b.divide(2, true);
			k++;
		}
	
		var t_positive;
		var t;
		if (a.isOdd()) {
			t = b;
			t_positive = false;
		} else {
			t = a;
			t_positive = true;
		}
		
		while (t.compare(0) != 0) {
			while (t.isEven())
				t = t.divide(2, true);
			if (t_positive)
				a = t;
			else
				b = t;
				
			t = a.dist(b);
			t_positive = a.compare(b) >= 0 ? true : false;
		}
		
		return new Natural(a.multiply(new Natural(2).pow(k)));
		
	}
	
		
	this.pow = function(Arg0) {
		// Beide Objekte Naturals, oder als Natural darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Natural(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Number("NaN");

		var Result = new Natural(1);
		for (var i = 0; i < Arg0.toString(); i++)
			Result = Result.multiply(this);
			
		return Result;		
	}
	
	this.compare = function(Arg0) {
		// Beide Objekte Naturals, oder als Natural darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Natural(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Number("NaN");
			
		var Comparator = Arg0.getValue();
		
		if (Value == Comparator)
			return 0;
				
		if (Value.length > Comparator.length)
			return 1;
		if (Value.length < Comparator.length)
			return -1;
				
		return Value.localeCompare(Comparator);		
	}
	
	this.multiply = function(Arg0) {
		// Beide Objekte Naturals, oder als Natural darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Natural(Arg0.toString());
		
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Natural("NaN");
		
		var Multiplier = Arg0.getValue();
		
		var Product = new Natural("0");
		var Carry = new Number(0);
		for (var i = Multiplier.length-1; i >= 0; i--) {
			var Summand = "";
			
			for (var j = i; j < Multiplier.length-1; j++)
				Summand += "0";

			var DigitA = Multiplier.charAt(i);

			for (var j = Value.length-1; j >= 0; j--)
			{
				var DigitB = Value.charAt(j);
				
				var Result = (DigitA * DigitB) + Carry;
				
				if (Result < 10)
				{
					Summand = "" + Result + Summand;
					Carry = 0;
				}
				else
				{
					Carry = new Number(Result.toString().charAt(0));
					Summand = Result.toString().charAt(1) + Summand;
				}				
			}
			if (Carry > 0)
				Summand = "" + Carry + Summand;
			
			Carry = 0;
			
			Product = Product.add(new Natural(Summand));
		}
		
		return Product;
	}
	
	this.dist = function(Arg0) {
		// Beide Objekte Naturals, oder als Natural darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Natural(Arg0.toString());
		
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Natural("NaN");

		// Sortieren der Operanden. OperandA soll der größere Summand sein.
		var Vergleich = this.compare(Arg0);
		if (Vergleich == 0) return new Natural("0");		
		var OperandA = Vergleich < 0 ? Arg0.getValue() : Value;
		var OperandB = Vergleich < 0 ? Value : Arg0.getValue(); 
	
		var Distance = "";
		var carry = false;
		
		for (var i = 1; i <= OperandA.length; i++)
		{
			var DigitA = new Number(OperandA.charAt(OperandA.length - i));
			var DigitB = new Number((OperandB.length - i) < 0 ? 0: OperandB.charAt(OperandB.length - i));
			
			if (carry) DigitB++;
			
			carry = DigitA < DigitB ?  true: false;

			var DigitC = (carry ? 10:0) + DigitA - DigitB;

			Distance = DigitC + Distance;
		}
		
		return new Natural(Distance.replace(/^0+/, ""));	
	}
	
	this.add = function(Arg0) {
		// Beide Objekte Naturals, oder als Natural darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Natural(Arg0.toString());
		
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Natural("NaN");
		
		// Sortieren der Summanden. SummandB soll der größere Summand sein.
		var Vergleich = this.compare(Arg0);
		var SummandA = Vergleich > 0 ? Arg0.getValue() : Value;
		var SummandB = Vergleich > 0 ? Value : Arg0.getValue(); 

		var Sum = "";
		var carry = false;
		
		for (var i = 1; i <= SummandB.length; i++)
		{
			var DigitA = new Number((SummandA.length - i) < 0 ? 0 : SummandA.charAt(SummandA.length - i));
			var DigitB = new Number(SummandB.charAt(SummandB.length - i));
					
			var DigitC = DigitA + DigitB;
			if (carry) DigitC++;			
			carry = DigitC > 9 ? true:false;
			if (DigitC > 9) DigitC -= 10;
			Sum = "" + DigitC + Sum			
		}
		
		if (carry) Sum = "1" + Sum;
		
		return new Natural(Sum);
	}
	
	this.getValue = function() {
		return Value;
	}

	this.toString = function() {
		return Value;	
	}
	
}

function Integer(Arg0) {
	// V 2.5
	
	var Signum; 			// false = positive true = negative
	var Value;				// Natural Number
	
	Arg0 = "" + Arg0;
	
	if (Arg0.match(/[\+-]?\d+/))
	{
		var FirstChar = Arg0.charAt(0);
		Signum = FirstChar.match(/\+|-/) ? (FirstChar.match(/-/) ? true:false) : false;
		Value = new Natural(FirstChar.match(/\+|-/) ? Arg0.substr(1):Arg0);
	} else {
		Value = new Natural("NaN");
	}
	
	this.getSignum = function () {
		return Signum;
	}

	this.compare = function(Arg0) {
		// Beide Objekte Integer, oder als Integer darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Integer(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Integer("NaN");
			
		var Comparator_Value = Arg0.getValue();
		var Comparator_Signum = Arg0.getSignum();
		
		if (Signum != Comparator_Signum)
		{
			if (Value.getValue() == Comparator_Value.getValue() && Comparator_Value.getValue() == "0")
				return 0;
				
			return Signum ? -1 : 1;
		}
		
		return (Signum ? -1:1) * Value.compare(Comparator_Value);
	}
	
	this.negate = function() {
		return new Integer ( (Signum ? "+":"-") + Value );
	}
	
	this.abs = function() {
		return new Integer(Value);
	}
	
	this.isNaN = function() {
		return Value == "NaN" ? true:false;
	}
	
	this.multiply = function(Arg0) {
		// Beide Objekte Integer, oder als Integer darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Integer(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Integer("NaN");

		var Multiplicand = this.getValue();
		var Multiplier = Arg0.getValue();

		var Product = new Integer((Signum != Arg0.getSignum() ? "-":"+") + Multiplicand.multiply(Multiplier).toString()) ;
		return Product;
	}
	
	this.dist = function(Arg0) {
		// Beide Objekte Integer, oder als Integer darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Integer(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Integer("NaN");
			
		return Signum != Arg0.getSignum() ? new Integer(Value.add(Arg0.getValue())) : new Integer (Value.dist(Arg0.getValue()));
		
	}
	
	this.subtract = function (Arg0) {
		// Beide Objekte Integer, oder als Integer darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Integer(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Integer("NaN");
		
		return this.add(Arg0.negate());
	}
	
	this.add = function (Arg0) {
		// Beide Objekte Integer, oder als Integer darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Integer(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Integer("NaN");
		
		if (Signum == Arg0.getSignum()) 
			return new Integer( (Signum ? "-":"+") + Value.add(Arg0.getValue()).toString());
		
		var Vergleich = Value.compare(Arg0.getValue());
	
		return new Integer( ((Vergleich > 0 ? Signum:Arg0.getSignum()) ? "-":"+") + Value.dist(Arg0.getValue()) );
	}
	
	this.divide = function(Arg0,Arg1) {
		// Beide Objekte Integer, oder als Integer darstellbar
		if (this.constructor != Arg0.constructor)
			Arg0 = new Integer(Arg0.toString());
			
		// Ist eine der Zahlen NaN ?
		if (this.isNaN() || Arg0.isNaN())
			return new Integer("NaN");

		var Dividend = this.getValue();
		var Divisor = Arg0.getValue();

		var Result = new Integer((Signum != Arg0.getSignum() ? "-":"+") + Dividend.divide(Divisor,Arg1).toString()) ;
		return Result;
	
	}
	
	this.kgV = function (Arg0) {
		return new Integer(Value.kgV(Arg0));
	}

	this.ggT = function(Arg0) {
		return new Integer(Value.ggT(Arg0))
	}
	
	this.pow = function(Arg0) {
		return new Integer(Value.isOdd ? (Signum ? "-":"") :Value.pow(Arg0));
	}
	
	this.isEven = function() {
		return Value.isEven();
	}
	
	this.isOdd = function() {
		return Value.isOdd();
	}	
	
	this.getValue = function () {
		return Value;
	}
	
	this.getSignum = function () {
		return Signum;
	}
	
	this.isPositive = function() {
		return !Signum;
	}
	
	this.isNegative = function() {
		return Signum;
	}
	
	this.toString = function() {
		return this.isNaN() ? Value.toString(): (Signum ? "-":"") + Value.toString();
	}	
}

function Rational(Arg0) {
	// V 0.8
	var Dividend = new Integer(0);
	var Divisor = new Natural(0); // Bedeuted soviel wie NaN, da Division durch 0

	Arg0 = "" + Arg0;

	if (Arg0.match(/^[\+-]?\d*(\.?\d*([eE][\+-]\d+)?)?$/))
	{
		var Parts = Arg0.toLowerCase().split("e");
		var Exponent = new Integer(Parts.length == 1 ? "0":Parts[1]);
		var Mantisse = Parts[0];
		
		var Signum = Mantisse.match(/^[\+-]/) ? Mantisse.substr(0,1) : "";
		Mantisse = Signum.length > 0 ? Mantisse.substr(1) : Mantisse;
		var CommaIndex = Mantisse.indexOf(".");
		Mantisse = Mantisse.replace(/\./, "");
		if (CommaIndex >= 0)
			Exponent = Exponent.subtract(Mantisse.length-CommaIndex);
		
		Dividend = new Integer(Signum + Mantisse);
		Divisor = new Natural(1);
		
		var ExponentDirection = Exponent.compare(0);
		if (Exponent.Direction != 0) {
			if (ExponentDirection > 0) {
				Dividend = Dividend.multiply(new Natural(10).pow(Exponent.getValue()));
			} else {
				Divisor = Divisor.multiply(new Natural(10).pow(Exponent.getValue()));
			}
		}
	} else if (Arg0.match(/^[\+-]?\d+\/\d+$/)) {
		var Parts = Arg0.split("/");
		Dividend = new Integer(Parts[0]);
		Divisor = new Natural(Parts[1]);
	}
	// Kürzen der Darstellung;
	cancel();
	
	this.divide = function(Arg0) {
		Arg0 = new Rational(Arg0);
		Arg0 = new Rational( (Arg0.isNegative() ? "-":"") + Arg0.getDivisor() + "/" + Arg0.getDividend().abs() );
		
		return this.multiply(Arg0);
	}

	this.isNaN = function () {
		return Divisor.compare(0) == 0 ? true:false;
	}
	
	this.isPositive = function () {
		if (this.isNaN())
			return null;
		
		return Dividend.isPositive();
	}

	this.isNegative = function (){
		if (this.isNaN())
			return null;
		
		return Dividend.isNegative();
	}
	
	this.add = function(Arg0) {
		Arg0 = new Rational(Arg0);
		return new Rational(Dividend.multiply(Arg0.getDivisor()).add(Arg0.getDividend().multiply(Divisor)).toString()+"/"+Divisor.multiply(Arg0.getDivisor()));
	}
	
	this.multiply = function(Arg0) {
		Arg0 = new Rational(Arg0);		
		return new Rational(Dividend.multiply(Arg0.getDividend()).toString()+"/"+Divisor.multiply(Arg0.getDivisor()));
	}
	
	this.getDividend = function () {
		return Dividend;
	}
	
	this.getDivisor = function() {
		return Divisor;
	}
	
	this.toString = function() {
			if (Divisor.compare(0) == 0)
				return "NaN";
		return ""+Dividend + "/" + Divisor.toString();
	}
	
	this.toDecimal = function(Arg0,Arg1,Arg2) {
		// Arg0 Anzahl der Dezimalstellen
		// Arg1 Rounding INT (-1 | 0 | 1 ) Round Floor, Arithmetic (default), Round Ceiling
		// Arg2 Fixed Decimals?
		Arg0 = new Number(typeof(Arg0) == "undefined" ? 10:arguments[0]);
		Arg1 = new Number(typeof(Arg1) == "undefined" ?  0:arguments[1]);
		Arg2 = new Number(typeof(Arg2) == "undefined" ?  false:arguments[2]);
		
		if (this.isNaN())
			return "NaN";
		
		var Precomma = Dividend.divide(Divisor,true);
		var Rest = Precomma.multiply(Divisor).dist(Dividend);
		if (Rest.compare(0) == 0 || Precomma.isNaN())
			return ""+Precomma;	
		
		var Returnwert = new String(""+Precomma);
		var MaxLength = Returnwert.length + Arg0 + 1;
		while (Returnwert.length < MaxLength && Rest.compare(0) != 0) {
			Rest = Rest.multiply(10);
			var Ergebnis = Rest.divide(Divisor,true);
			Rest = Ergebnis.multiply(Divisor).dist(Rest);
			Returnwert += Ergebnis;
		}
		
		
		// Anhängen von nullen falls gewünscht
		if (Arg2)
			for (var i = Returnwert.length; i < MaxLength; i++)
				Returnwert += "0";
				

		// Runden der letzten Stelle
		if (Returnwert.length == MaxLength) {
			
			var RoundingDigit = Returnwert.charAt(MaxLength-1);
			var NaturalRepresentation = new Natural(Returnwert.substr(0,MaxLength-1).replace(/-/g,""));
			var Rounding = ( (Arg1 > 0 && RoundingDigit > 0 ) || (Arg1 == 0 && RoundingDigit >= 5) ) ? 1 : 0;
			NaturalRepresentation = NaturalRepresentation.add(Rounding).toString();
			
			// Ist eine Stelle dazugekommen?
			var NR_length = NaturalRepresentation.length
			if (NaturalRepresentation.charAt(NR_length -1) == 0 && Rounding == 1) {
				NaturalRepresentation = NaturalRepresentation.substr(0, NR_length -1);
				NR_length--;
			}
			
			// Zusammensetzen des Strings
			Returnwert = (this.isNegative() ? "-":"") + NaturalRepresentation.substr(0, NR_length - Arg0) + "."
						+ NaturalRepresentation.substr(NR_length - Arg0);
			
		}
		
		
		return Returnwert.replace(/\.$/, "");	
	}
	
	function cancel() {
		// Kürzen, nur wenn Dividend und Divisor größer als 1 ist
		if (Divisor.compare(1) > 0 && Dividend.abs().compare(1) > 0)
		{
			if (Dividend.compare(0) == 0) {
				Divisor = new Natural(1);
			} else {
				var Teiler = Dividend.ggT(Divisor);
				Dividend = Dividend.divide(Teiler);
				Divisor = Divisor.divide(Teiler);
			}
		}
	}
}


function GlobalNumber() {
	// Arguments: 0 Value as JavaScript Number
	
	var rationalValue = new Rational(GlobalNumber.arguments[0]);
	
	this.getNumericValue = function () { return new Number(rationalValue.toDecimal()); }
	
	this.toEnglishString = function () {
		// Arguments: 0 Decimals Muß 0 oder größer sein
		// Arguments: 1 Rounding INT (-1 | 0 | 1 ) Round Floor, Arithmetic (default), Round Ceiling
		// Arguments: 2 Fixed length of Postcomma?
		var Decimals = arguments[0] != null ? arguments[0]:-1;
		var Rounding = arguments[1] != null ? arguments[1]: 0;
		var Fixed =    arguments[2] != null ? arguments[2]: false;		

		return rationalValue.toDecimal(Decimals,Rounding,Fixed); 
	}
		
	this.toGermanString = function (Decimals, Rounding) {
		var Returnvalue = this.toEnglishString(Decimals, Rounding)+"";
		// Replacement of Symbols K=Komma
		Returnvalue = Returnvalue.replace( /\./, "K");
		Returnvalue = Returnvalue.replace( /\,/g, ".");
		Returnvalue = Returnvalue.replace( /K/, ",");
		return Returnvalue;
	}
	
	this.setEnglishValue = function (Value) { rationalValue = new Rational(Value+""); return this;}
	this.setGermanValue = function (Value) {
		Value += "";
		// Entfernen aller Punkte und des führenden +, da sie nicht von Bedeutung sind.
		Value = Value.replace( /(^\+|\.+)/g, ""); 
		// Ersetzen des Beistrich-Komma durch ein Punkt-Komma
		Value = Value.replace( /\,/, ".");
		// Speichern des Wertes
		rationalValue = new Rational(Value);
		return this;
	}	
}

// Original JavaScript code by Duncan Crombie: dcrombie at chirp.com.au
// Please acknowledge use of this code by including this header.
// START

var bikky = document.cookie; // retrieve cookie string
var today = new Date();

function getCookie(name) { // use: getCookie("name");
	var index = bikky.indexOf(name + "=");
	if (index == -1) return null;
	index = bikky.indexOf("=", index) + 1;
	var endstr = bikky.indexOf(";", index);
	if (endstr == -1) endstr = bikky.length;
	return unescape(bikky.substring(index, endstr));
}

function setCookie(name, value, path, expiry) { // use: setCookie("name", value);
	var expiry = ( expiry == null) ? new Date(today.getTime() + 356 * 24 * 60 * 60 * 1000) : expiry;
	var path = ( path == null) ? "/" : path;
	if (value != null && value != "")
		document.cookie=name + "=" + escape(value) + "; expires=" + expiry.toGMTString() + "; path=" + path;
	bikky = document.cookie; // update bikky
}

function isCookiesEnabled() {
	var enabled;
	var exp = new Date();
	exp.setTime(exp.getTime() + (60*1000));
	// valid: one minute (60seconds*1000 hundreds)
	SetCookie ('CookieEnabledCheck', 1, exp);
	enabled = GetCookie('CookieEnabledCheck');
	if (enabled == null)
		return false;
	return true;
}

// Original JavaScript code by Duncan Crombie: dcrombie at chirp.com.au
// Please acknowledge use of this code by including this header.
// END


// String Methods falls diese dem Browser fehlen
if ( !String.prototype.caseValue ) String.prototype.caseValue = function()
{
	return (this.toLowerCase() == this) ? 0 : 1;
}

if ( !String.prototype.compareChars ) String.prototype.compareChars = function(a,b)
{
	if ( a.caseValue() < b.caseValue() ) return -1;
	if ( a.caseValue() > b.caseValue() ) return 1;
	if ( a < b ) return -1;
	if ( a > b ) return 1;
	return 0;
}

if ( !String.prototype.compare ) String.prototype.compare = function(that)
{
	var i = 0;
	while ( i < Math.min(this.length,that.length) )
	{
		var c = this.compareChars(this.charAt(i),that.charAt(i));
		if ( c != 0 ) return c;
		i++;
	}
	if ( this.length < that.length ) return -1;
	if ( this.length > that.length ) return 1;
	return 0;
}

if ( !String.prototype.localeCompare ) String.prototype.localeCompare = function(that)
{
	var sThis = this.toLocaleUpperCase();
	var sThat = that.toLocaleUpperCase();
	var r = sThis.compare(sThat);
	if ( r != 0 ) return r;
	return this.compare(that);
}