Finding e
In mathematics we have a few enigmatic numbers, of with pi and e are the best known ones. Pi is the ratio
between diameter and circumference of the circle and e is the base of the natural logarithm. The nice part
about 'e' is that it is defined in a simple mathematical formula:
And this formula is easy to implement in any programming language. Even in Java... So I set out to test my
limited knowledge of Java and see how accurate Java math is.
Attempt 1: shE0.java
No beating around the bush. Let's get cracking. Here's the source of shE0.java:
class shE0
{
public static void main ( String args [] )
{
float fraction, result = 1.0;
int n;
try
{
n = Integer.parseInt (args [0]);
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println ("Usage : shE number ");
System.out.println ("Aborting.");
return;
}
catch (NumberFormatException e)
{
System.out.println ("Error converting number " + args [0] + ". Aborting");
return;
}
fraction = 1.0 + 1.0 / n;
System.out.println ("Fraction = " + fraction);
System.out.println ("Calculating 'e' using pow : " + Math.pow (fraction, n));
while (n > 0)
{
result = result * fraction;
--n;
}
System.out.println ("Calculating 'e' using loop : " + result);
System.out.println ("'e' according to Math.E : " + Math.E);
}
}
See this source: Java uses qualified imports. No IMPORT statement rquired though. Apparently the compiler is
colossal enough to find out things by itself. Not very assuring, but this language is collosal so let's give
it the benefit of the doubt. The qualified imports in this example were:
jan@Beryllium:~/develop/java$ javac shE0.java
shE0.java:5: possible loss of precision
found : double
required: float
float fraction, result = 1.0;
^
shE0.java:25: possible loss of precision
found : double
required: float
fraction = 1.0 + 1.0 / n;
^
2 errors
jan@Beryllium:~/develop/java$ jed shE0.java
This is new to me. Error while compiling test programs. That's good. I like new experiences.. :o)
Attempt 2: shE1.java
OK, so I have changed the source and to keep this webpage within the reasonable, I only list the changes:
class shE1 float fraction, result = 1.0f; ... ... fraction = 1.0f + 1.0f / (float) n;Let's see if this compiles. Programming requires a lot of trial and error tests, as you will find out. Keep your fingers crossed!
jan@Beryllium:~/develop/java$ javac shE1.java jan@Beryllium:~/develop/java$Now, THAT's more like it. No errors during compilation. Let's see how java runs my source:
jan@Beryllium:~/develop/java$ java shE1 Usage : shE1 number Aborting. jan@Beryllium:~/develop/java$ java shE1 10 Fraction = 1.1 Calculating 'e' using pow : 2.593743022278593 Calculating 'e' using loop : 2.5937428 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shE1 1000 Fraction = 1.001 Calculating 'e' using pow : 2.717050770326506 Calculating 'e' using loop : 2.7170494 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shE1 100000 Fraction = 1.00001 Calculating 'e' using pow : 2.7219622037713953 Calculating 'e' using loop : 2.7219107 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shE1 10000000 Fraction = 1.0000001 Calculating 'e' using pow : 3.293967694905941 Calculating 'e' using loop : 2.8841858 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shE1 1000000 Fraction = 1.000001 Calculating 'e' using pow : 2.595226670281386 Calculating 'e' using loop : 2.5898523 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shE1 100000 Fraction = 1.00001 Calculating 'e' using pow : 2.7219622037713953 Calculating 'e' using loop : 2.7219107 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$The first test was obvious: I forgot to specify the value for 'n'. But the program caught my error and corrected me. Good. Try and catch are working. In the next lines I run shE1 with several values of 'n'. The value of 'fraction' is calculated correct here. On another machine, 1 + 1/100 was 1.010001265 which of course is false. The values for 'e' gets better when n goes up. That's in accordance with the theory. But the accuracy goes down again when n exceeds 100,000 (a hundred thousand). Hmm strange. Apparently the fraction is difficult to express in binary. Also: look at what Math.pow returns and what our loop does: the loop value stays within reason from the real value. For 'n' is 10 million, Math.pow returns a value of 'e' that exceeds pi!
Attempt 3: shEd.java
I call this attempt 3, but in reality it was attempt 20 odd. I ran the tests on my laptop and I remember that I got a lot of very stange results.. So I had to check more versions than on this Pentium IV system. Still, here's the new version of shE, which is now called 'shEd' since it switches over to doubles.
class shEd
{
public static void main ( String args [] )
{
double fraction, result = 1.0d;
int n;
try
{
n = Integer.parseInt (args [0]);
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println ("Usage : shE number ");
System.out.println ("Aborting.");
return;
}
catch (NumberFormatException e)
{
System.out.println ("Error converting number " + args [0] + ". Aborting");
return;
}
fraction = 1.0d + 1.0d / (double) n;
System.out.println ("n = " + n + " and fraction = " + fraction);
System.out.println ("Calculating 'e' using pow : " + Math.pow (fraction, n));
while (n > 0)
{
result = result * fraction;
--n;
}
System.out.println ("Calculating 'e' using loop : " + result);
System.out.println ("'e' according to Math.E : " + Math.E);
}
}
Let's see how this compiles:
jan@Beryllium:~/develop/java$ javac shEd.java jan@Beryllium:~/develop/java$That's a good thing. Let's now run it:
jan@Beryllium:~/develop/java$ java shEd Usage : shE number Aborting. jan@Beryllium:~/develop/java$ java shEd 10 n = 10 and fraction = 1.1 Calculating 'e' using pow : 2.5937424601000023 Calculating 'e' using loop : 2.5937424601000023 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd 100 n = 100 and fraction = 1.01 Calculating 'e' using pow : 2.7048138294215285 Calculating 'e' using loop : 2.7048138294215294 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd 1000 n = 1000 and fraction = 1.001 Calculating 'e' using pow : 2.7169239322355936 Calculating 'e' using loop : 2.7169239322355985 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd 10000 n = 10000 and fraction = 1.0001 Calculating 'e' using pow : 2.7181459268249255 Calculating 'e' using loop : 2.7181459268248984 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd 100000 n = 100000 and fraction = 1.00001 Calculating 'e' using pow : 2.7182682371922975 Calculating 'e' using loop : 2.718268237192295 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd 1000000 n = 1000000 and fraction = 1.000001 Calculating 'e' using pow : 2.7182804690957534 Calculating 'e' using loop : 2.7182804690959363 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd 10000000 n = 10000000 and fraction = 1.0000001 Calculating 'e' using pow : 2.7182816941320818 Calculating 'e' using loop : 2.7182816941320103 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd 100000000 n = 100000000 and fraction = 1.00000001 Calculating 'e' using pow : 2.7182817983473577 Calculating 'e' using loop : 2.71828179834636 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd 1000000000 n = 1000000000 and fraction = 1.000000001 Calculating 'e' using pow : 2.7182820520115603 Calculating 'e' using loop : 2.7182820520118995 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd 10000000000 Error converting number 10000000000. Aborting jan@Beryllium:~/develop/java$It compiles good and it runs good. No arguments triggers the catcher. And a too great argument (10 billion, which exceeds the range of the integer values) also makes us get kicked out. That's a nice thing and it's built in the language.
Attempt 4: shEd2.java
In this source, I calculate the difference between the calculated values with the value defined in Math.E. Here's the source:
class shEd1
{
public static void main ( String args [] )
{
double mpval, fraction, delta1, delta2, result = 1.0d;
int n;
try
{
n = Integer.parseInt (args [0]);
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println ("Usage : shE number ");
System.out.println ("Aborting.");
return;
}
catch (NumberFormatException e)
{
System.out.println ("Error converting number " + args [0] + ". Aborting");
return;
}
fraction = 1.0d + 1.0d / (double) n;
mpval = Math.pow (fraction, n);
delta1 = mpval - Math.E;
System.out.println ("n = " + n + " and fraction = " + fraction);
System.out.println ("Calculating 'e' using pow : " + mpval + " delta = " + delta1 );
while (n > 0)
{
result = result * fraction;
--n;
}
delta2 = result - Math.E;
System.out.println ("Calculating 'e' using loop : " + result + " delta = " + delta2 );
System.out.println ("'e' according to Math.E : " + Math.E);
}
}
The red lines were changed. Let's see how we do now:
jan@Beryllium:~/develop/java$ java shEd1 10 n = 10 and fraction = 1.1 Calculating 'e' using pow : 2.5937424601000023 delta = -0.12453936835904278 Calculating 'e' using loop : 2.5937424601000023 delta = -0.12453936835904278 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd1 100 n = 100 and fraction = 1.01 Calculating 'e' using pow : 2.7048138294215285 delta = -0.01346799903751661 Calculating 'e' using loop : 2.7048138294215294 delta = -0.013467999037515721 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd1 1000 n = 1000 and fraction = 1.001 Calculating 'e' using pow : 2.7169239322355936 delta = -0.0013578962234515046 Calculating 'e' using loop : 2.7169239322355985 delta = -0.0013578962234466196 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd1 1000000 n = 1000000 and fraction = 1.000001 Calculating 'e' using pow : 2.7182804690957534 delta = -1.359363291708604E-6 Calculating 'e' using loop : 2.7182804690959363 delta = -1.3593631087438496E-6 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd1 10000000 n = 10000000 and fraction = 1.0000001 Calculating 'e' using pow : 2.7182816941320818 delta = -1.3432696333026684E-7 Calculating 'e' using loop : 2.7182816941320103 delta = -1.3432703482862962E-7 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd1 100000000 n = 100000000 and fraction = 1.00000001 Calculating 'e' using pow : 2.7182817983473577 delta = -3.011168736577474E-8 Calculating 'e' using loop : 2.71828179834636 delta = -3.0112685234229275E-8 'e' according to Math.E : 2.718281828459045 jan@Beryllium:~/develop/java$ java shEd1 1000000000 n = 1000000000 and fraction = 1.000000001 Calculating 'e' using pow : 2.7182820520115603 delta = 2.2355251516614771E-7 Calculating 'e' using loop : 2.7182820520118995 delta = 2.2355285445030404E-7 'e' according to Math.E : 2.718281828459045Some observations:
jan@Beryllium:~/develop/java$ time java shEd1 1000000000 n = 1000000000 and fraction = 1.000000001 Calculating 'e' using pow : 2.7182820520115603 delta = 2.2355251516614771E-7 Calculating 'e' using loop : 2.7182820520118995 delta = 2.2355285445030404E-7 'e' according to Math.E : 2.718281828459045 real 0m5.254s user 0m5.180s sys 0m0.016s jan@Beryllium:~/develop/java$Five seconds calculation time on a 3 GHz dual core Pentium IV... Imagine how long that would take on a 3 MHz Sinclair ZX 81...
Conclusions
All in all, Java does not perform that bad... It's all in the book that you are reading to learn the language.
I started out with many books that used a top down approach to teach Java. Always looking back to C, C++ and
other languages. The "Java in easy steps" book uses a normal method: it teachs simple things that get
complexer by the chapter. This seems to work for me.
Java
Page created on 4 June 2010 and
Page equipped with FroogleBuster technology