approximate pi by iteration JAVA - java

I am trying to approximate pi by iteration. This is only a portion of the code.
I'm trying to put this equation into java: pi = 4(1 - 1/3 + 1/5 - 1/7 + 1/9 + ... + ((-1)^(i+1)) / (2i - 1) ). The problem I have is the summation of this equation (illustrated in my code). If the user keeps on entering y, the program is supposed to multiply i by 2 and calculate pi until user enters n, then it returns to the main menu.
else if(input == 4)
{
System.out.print("i=1 pi=4.0\tWould you like to continue? (y|n) ");
char y = keyboard.next().charAt(0);
if (y =='y')
{
for (int i=2; i<=1000; i=i*2)
{
int sum = 0;
double pi =4 * (Math.pow(-1, i+1)/(2*i-1));
//Right here, how do I modify it to get a sum across a multitude of i's?
System.out.print("i=" + i + " " + "pi" + "=" + pi + "\tcontinue (y|n)? " );
keyboard.next().charAt(0);
}
}
else
{
}

I think your issue is the difference between the summation equation using i and the programmatic way to loop through a calculation. Something like this will loop through is adding/subtracting the fraction, and then multiply it all by 4 in the end.
boolean plus = true
double sum = 0;
for (double i=1.0; i<=1000; i+=2.0)
{
if (plus) {
sum += 1.0/i;
plus = false;
} else {
sum -= 1.0/i;
plus = true;
}
}
sum *= 4;

Related

Why does this java code to count digit of floating value goes in loop for this value?

import java.util.Scanner;
class FloatDigit {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double n = sc.nextDouble();
int x = (int) n;
int count = 0;
do {
count++;
x = x / 10;
} while (x != 0);
System.out.println("Before Decimal Digits: " + count);
//it gets stuck from here only
do {
count++;
n = n * 10;
} while (n != (int) n);
System.out.println(count + " total digits present in there in number.");
}
}
This goes in an infinite loop for the value: 58.2354/58.234. It is working fine with other values too and longer values too.
If some debug logging is added to the second loop, it can be seen, that when multiplying a double number by 10, there is a tiny error which does not allow the comparison n == (int) n ever become true.
It is actually a known issue that floating-point arithmetics has a certain computation error, so it should be taken into account when comparing the double n to its counterpart with the decimal point shifted right:
do {
count++;
n = n * 10;
System.out.println(count + " - " + n);
} while (Math.abs(n - (int) n) > 1E-7);
System.out.println(count + " total digits present in the number.");
Output:
58.234
Before Decimal Digits: 2
3 - 582.34
4 - 5823.400000000001
5 - 58234.00000000001
5 total digits present in the number.

java Sine(x) Taylor Series

Can someone help me for geting out this code of sin(x) Tailor function to get followings:
The first 4 sin(x) Tailor series.
To calculating the sin function using the sum-formel
How to write a method public static double MySinApproximate( double x)?
That is what i get so far, and it has to be in this way!!
import java.lang.Math;
public class mysin {
public static void main(String[] args){
double x= Math.PI;
System.out.println( MySin(x) + "\t \t" + Math.sin(x) + "\n" );
}
public static double MySin(double x){
double sumNeu, sumOld, sum;
int i = 1;
sum = sumNeu = x; // This should calculating the first term Value
do //the loop do will calculating the Tailor Series
{
sumOld = sumNeu;
i++; sum = + sum * x * x / i;
i++; sum = sum / i;
sumNeu = sumOld + sum;
}
while( sumNeu != sumOld);
return sumNeu;
}
} // 11.548739357257745 1.2246467991473532E-16 (as output)
Your loop isn't calculating the Taylor series correctly. (This is really a Maclaurin series, which is the special case of a Taylor series with a = 0.) For the sine function, the terms need to be added and subtracted in an alternating fashion.
sin(x) = x - x3/3! + x5/5! - ...
Your method only adds the terms.
sin(x) = x + x3/3! + x5/5! + ...
Flip the sign of sum on each iteration, by adding the designated line:
do // The loop will calculate the Taylor Series
{
sumOld = sumNeu;
i++; sum = + sum * x * x / i;
i++; sum = sum / i;
sum = -sum; // Add this line!
sumNeu = sumOld + sum;
}
With this change I get a result that is very close:
2.3489882528577605E-16 1.2246467991473532E-16
Due to the inherent inaccuracies of floating-point math in Java (and IEEE in general), this is likely as close as you'll get by writing your own sine method.
I tested an additional case of π/2:
System.out.println( MySin(x/2) + "\t \t" + Math.sin(x/2) + "\n" );
Again, it's close:
1.0000000000000002 1.0
1.I want to write all again like that -
2.I try to writing the first 4 series from sine Taylor and the proximity all together but anyhow doesn't work correctly -
3.i get this output
0.0 0.8414709848078965
0.8414709848078965 0.9092974268256817
0.8414709848078965 0.1411200080598672
0.9092974268256817 -0.7568024953079282
4.How can i get the same accuracy
1.0000000000000002 1.0
and the series of sine(x)?
public class MySin {
public static void main(String[] args){
double y = 0;
y = 4;
for (int i = 1; i<= y; i++){
System.out.println( MySin(i/2) + "\t \t" + Math.sin(i) + "\n" );
}
}
public static double MySin(double x){
double sumNew, sumOld, sum;
int i = 1;
sum = sumNew = x; // This should calculating the first term Value
do //the loop do will calculating the Tailor Series
{
sumOld = sumNew;
i++; sum = - sum * x * x / i; // i did change the sign to -
i++; sum = sum / i;
sum = - sum; // so i don't need this line anymore
sumNew = sumOld + sum;
}
while( sumNew != sumOld);
return sumNew;
}
public static double MySineProximity ( double x) {
while ( x <= ( Math.PI /2 ) )
{
x = 0;
}
return MySin (x);
}
}

Fraction-decimal(and vice versa) converter

I have 2 parts of code, the first one being converting fraction to decimal, and the second one being converting decimal to fraction.
However, I have to combine the two piece of code together and I have no idea.I want it to detect the input as either doubles or fraction and convert it to the other.
import java.util.*;
public class ExcerciseEleven {
public static void main (String[] args) {
Scanner sc = new Scanner (System.in);
System.out.println("Enter Numerator: ");
int numerator = sc.nextInt();
System.out.println("Enter Denominator: ");
int denominator = sc.nextInt();
if (denominator == 0) {
System.out.println("Can't divide by zero");
}
else {
double fraction = (double)numerator / denominator;
System.out.println(fraction);
}
}
}
public class Fractions {
public static void main(String args[]) {
double decimal;
double originalDecimal;
int LIMIT = 12;
int denominators[] = new int[LIMIT + 1];
int numerator, denominator, temp;
int MAX_GOODNESS = 100;
// Get a number to be converted to a fraction
if (args.length == 1) {
decimal = Double.valueOf(args[0]).doubleValue();
} else {
// No number was given, so just use pi
assert args.length == 0;
decimal = Math.PI;
}
originalDecimal = decimal;
// Display the header information
System.out.println("-------------------------------------------------------");
System.out.println("Program by David Matuszek");
System.out.println("Input decimal number to be converted: " + decimal);
System.out.println();
// Compute all the denominators
System.out.println("All computed denominators:");
int i = 0;
while (i < LIMIT + 1) {
denominators[i] = (int)decimal;
System.out.print(denominators[i] + " ");
decimal = 1.0 / (decimal - denominators[i]);
i = i + 1;
}
System.out.println();
System.out.println();
// Compute the i-th approximation
int last = 0;
while (last < LIMIT) {
// Print out the denominators used in this computation
System.out.print("Using these " + (last + 1) + " denominators: ");
for (int j = 0; j <= last; j++) {
System.out.print(denominators[j] + " ");
}
System.out.println();
// Initialize variables used in computation
numerator = 1;
denominator = 1;
temp = 0;
// Do the computation
int current = last;
while (current >= 0) {
denominator = numerator;
numerator = (numerator * denominators[current]) + temp;
temp = denominator;
current = current - 1;
}
last = last + 1;
// Display results
double value = (double)numerator/denominator;
int goodness = denominators[last];
double error = 100 * Math.abs(value - originalDecimal) / originalDecimal;
System.out.print("fraction = " + (int)numerator + "/" +
(int)denominator);
System.out.print(", value = " + value);
System.out.print(", goodness = " + goodness);
System.out.println(", error = " + (int)error + "%");
System.out.println();
// Exit early if we have reached our goodness criterion
if (Math.abs(goodness) > MAX_GOODNESS) break;
}
}
}
If I was doing it all on one prompt, I would make two static methods Fraction.TryParse(), and I would use the built in Double.TryParse(), if decimal.TryParse returns true then you do in fact have a decimal. If it returns false, then you have a Fraction, therefore you have to use the same string you passed into Decimal.TryParse() in Fraction.TryParse(). Of course you will need some sanity checks in your Fraction.TryParse() method. The prompt could look something like this:
Enter Decimal/Fraction: 3.14
Enter Decimal/Fraction: 1 + 1/2
Enter Decimal/Fraction: 1 1/2
Enter Decimal/Fraction: 1 (1/2)
You see, if you want this all on one line you need some way to be able to delimit the characters, like a space, or brackets, or simply a + sign which would be mathematically accurate. If it is all on one line it also simplifies your program a little bit because you don't have multiple prompts for one object. The "1 (1/2)" input is not technically mathematically accurate, but you can kind of see how the data is supposed to be structured, you just can't be mathematically rigid with that prompt.
Here I am using the fraction one and one half, your implementation doesn't have a mixed number implementation, but you could just input 1/2 or something, just regular fractions.

Riemann Zeta Function in Java - Infinite Recursion with Functional Form

Note: Updated on 06/17/2015. Of course this is possible. See the solution below.
Even if anyone copies and pastes this code, you still have a lot of cleanup to do. Also note that you will have problems inside the critical strip from Re(s) = 0 to Re(s) = 1 :). But this is a good start.
import java.util.Scanner;
public class NewTest{
public static void main(String[] args) {
RiemannZetaMain func = new RiemannZetaMain();
double s = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.print("Enter the value of s inside the Riemann Zeta Function: ");
try {
s = scan.nextDouble();
}
catch (Exception e) {
System.out.println("You must enter a positive integer greater than 1.");
}
start = System.currentTimeMillis();
if (s <= 0)
System.out.println("Value for the Zeta Function = " + riemannFuncForm(s));
else if (s == 1)
System.out.println("The zeta funxtion is undefined for Re(s) = 1.");
else if(s >= 2)
System.out.println("Value for the Zeta Function = " + getStandardSum(s));
else
System.out.println("Value for the Zeta Function = " + getNewSum(s));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
// Standard form the the Zeta function.
public static double standardZeta(double s) {
int n = 1;
double currentSum = 0;
double relativeError = 1;
double error = 0.000001;
double remainder;
while (relativeError > error) {
currentSum = Math.pow(n, -s) + currentSum;
remainder = 1 / ((s-1)* Math.pow(n, (s-1)));
relativeError = remainder / currentSum;
n++;
}
System.out.println("The number of terms summed was " + n + ".");
return currentSum;
}
public static double getStandardSum(double s){
return standardZeta(s);
}
//New Form
// zeta(s) = 2^(-1+2 s)/((-2+2^s) Gamma(1+s)) integral_0^infinity t^s sech^2(t) dt for Re(s)>-1
public static double Integrate(double start, double end) {
double currentIntegralValue = 0;
double dx = 0.0001d; // The size of delta x in the approximation
double x = start; // A = starting point of integration, B = ending point of integration.
// Ending conditions for the while loop
// Condition #1: The value of b - x(i) is less than delta(x).
// This would throw an out of bounds exception.
// Condition #2: The value of b - x(i) is greater than 0 (Since you start at A and split the integral
// up into "infinitesimally small" chunks up until you reach delta(x)*n.
while (Math.abs(end - x) >= dx && (end - x) > 0) {
currentIntegralValue += function(x) * dx; // Use the (Riemann) rectangle sums at xi to compute width * height
x += dx; // Add these sums together
}
return currentIntegralValue;
}
private static double function(double s) {
double sech = 1 / Math.cosh(s); // Hyperbolic cosecant
double squared = Math.pow(sech, 2);
return ((Math.pow(s, 0.5)) * squared);
}
public static double getNewSum(double s){
double constant = Math.pow(2, (2*s)-1) / (((Math.pow(2, s)) -2)*(gamma(1+s)));
return constant*Integrate(0, 1000);
}
// Gamma Function - Lanczos approximation
public static double gamma(double s){
double[] p = {0.99999999999980993, 676.5203681218851, -1259.1392167224028,
771.32342877765313, -176.61502916214059, 12.507343278686905,
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7};
int g = 7;
if(s < 0.5) return Math.PI / (Math.sin(Math.PI * s)*gamma(1-s));
s -= 1;
double a = p[0];
double t = s+g+0.5;
for(int i = 1; i < p.length; i++){
a += p[i]/(s+i);
}
return Math.sqrt(2*Math.PI)*Math.pow(t, s+0.5)*Math.exp(-t)*a;
}
//Binomial Co-efficient - NOT CURRENTLY USING
/*
public static double binomial(int n, int k)
{
if (k>n-k)
k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
} */
// Riemann's Functional Equation
// Tried this initially and utterly failed.
public static double riemannFuncForm(double s) {
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
double nextTerm = Math.pow(2, (1-s))*Math.pow(Math.PI, (1-s)-1)*(Math.sin((Math.PI*(1-s))/2))*gamma(1-(1-s));
double error = Math.abs(term - nextTerm);
if(s == 1.0)
return 0;
else
return Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)*standardZeta(1-s);
}
}
Ok well we've figured out that for this particular function, since this form of it isn't actually a infinite series, we cannot approximate using recursion. However the infinite sum of the Riemann Zeta series (1\(n^s) where n = 1 to infinity) could be solved through this method.
Additionally this method could be used to find any infinite series' sum, product, or limit.
If you execute the code your currently have, you'll get infinite recursion as 1-(1-s) = s (e.g. 1-s = t, 1-t = s so you'll just switch back and forth between two values of s infinitely).
Below I talk about the sum of series. It appears you are calculating the product of the series instead. The concepts below should work for either.
Besides this, the Riemann Zeta Function is an infinite series. This means that it only has a limit, and will never reach a true sum (in finite time) and so you cannot get an exact answer through recursion.
However, if you introduce a "threshold" factor, you can get an approximation that is as good as you like. The sum will increase/decrease as each term is added. Once the sum stabilizes, you can quit out of recursion and return your approximate sum. "Stabilized" is defined using your threshold factor. Once the sum varies by an amount less than this threshold factor (which you have defined), your sum has stabilized.
A smaller threshold leads to a better approximation, but also longer computation time.
(Note: this method only works if your series converges, if it has a chance of not converging, you might also want to build in a maxSteps variable to cease execution if the series hasn't converged to your satisfaction after maxSteps steps of recursion.)
Here's an example implementation, note that you'll have to play with threshold and maxSteps to determine appropriate values:
/* Riemann's Functional Equation
* threshold - if two terms differ by less than this absolute amount, return
* currSteps/maxSteps - if currSteps becomes maxSteps, give up on convergence and return
* currVal - the current product, used to determine threshold case (start at 1)
*/
public static double riemannFuncForm(double s, double threshold, int currSteps, int maxSteps, double currVal) {
double nextVal = currVal*(Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)); //currVal*term
if( s == 1.0)
return 0;
else if ( s == 0.0)
return -0.5;
else if (Math.abs(currVal-nextVal) < threshold) //When a term will change the current answer by less than threshold
return nextVal; //Could also do currVal here (shouldn't matter much as they differ by < threshold)
else if (currSteps == maxSteps)//When you've taken the max allowed steps
return nextVal; //You might want to print something here so you know you didn't converge
else //Otherwise just keep recursing
return riemannFuncForm(1-s, threshold, ++currSteps, maxSteps, nextVal);
}
}
This is not possible.
The functional form of the Riemann Zeta Function is --
zeta(s) = 2^s pi^(-1+s) Gamma(1-s) sin((pi s)/2) zeta(1-s)
This is different from the standard equation in which an infinite sum is measured from 1/k^s for all k = 1 to k = infinity. It is possible to write this as something similar to --
// Standard form the the Zeta function.
public static double standardZeta(double s) {
int n = 1;
double currentSum = 0;
double relativeError = 1;
double error = 0.000001;
double remainder;
while (relativeError > error) {
currentSum = Math.pow(n, -s) + currentSum;
remainder = 1 / ((s-1)* Math.pow(n, (s-1)));
relativeError = remainder / currentSum;
n++;
}
System.out.println("The number of terms summed was " + n + ".");
return currentSum;
}
The same logic doesn't apply to the functional equation (it isn't a direct sum, it is a mathematical relationship). This would require a rather clever way of designing a program to calculate negative values of Zeta(s)!
The literal interpretation of this Java code is ---
// Riemann's Functional Equation
public static double riemannFuncForm(double s) {
double currentVal = (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s));
if( s == 1.0)
return 0;
else if ( s == 0.0)
return -0.5;
else
System.out.println("Value of next value is " + nextVal(1-s));
return currentVal;//*nextVal(1-s);
}
public static double nextVal(double s)
{
return (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s));
}
public static double getRiemannSum(double s) {
return riemannFuncForm(s);
}
Testing on three or four values shows that this doesn't work. If you write something similar to --
// Riemann's Functional Equation
public static double riemannFuncForm(double s) {
double currentVal = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s); //currVal*term
if( s == 1.0)
return 0;
else if ( s == 0.0)
return -0.5;
else //Otherwise just keep recursing
return currentVal * nextVal(1-s);
}
public static double nextVal(double s)
{
return (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s));
}
I was misinterpretation how to do this through mathematics. I will have to use a different approximation of the zeta function for values less than 2.
I think I need to use a different form of the zeta function. When I run the entire program ---
import java.util.Scanner;
public class Test4{
public static void main(String[] args) {
RiemannZetaMain func = new RiemannZetaMain();
double s = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.print("Enter the value of s inside the Riemann Zeta Function: ");
try {
s = scan.nextDouble();
}
catch (Exception e) {
System.out.println("You must enter a positive integer greater than 1.");
}
start = System.currentTimeMillis();
if(s >= 2)
System.out.println("Value for the Zeta Function = " + getStandardSum(s));
else
System.out.println("Value for the Zeta Function = " + getRiemannSum(s));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
// Standard form the the Zeta function.
public static double standardZeta(double s) {
int n = 1;
double currentSum = 0;
double relativeError = 1;
double error = 0.000001;
double remainder;
while (relativeError > error) {
currentSum = Math.pow(n, -s) + currentSum;
remainder = 1 / ((s-1)* Math.pow(n, (s-1)));
relativeError = remainder / currentSum;
n++;
}
System.out.println("The number of terms summed was " + n + ".");
return currentSum;
}
public static double getStandardSum(double s){
return standardZeta(s);
}
// Riemann's Functional Equation
public static double riemannFuncForm(double s, double threshold, double currSteps, int maxSteps) {
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
//double nextTerm = Math.pow(2, (1-s))*Math.pow(Math.PI, (1-s)-1)*(Math.sin((Math.PI*(1-s))/2))*gamma(1-(1-s));
//double error = Math.abs(term - nextTerm);
if(s == 1.0)
return 0;
else if (s == 0.0)
return -0.5;
else if (term < threshold) {//The recursion will stop once the term is less than the threshold
System.out.println("The number of steps is " + currSteps);
return term;
}
else if (currSteps == maxSteps) {//The recursion will stop if you meet the max steps
System.out.println("The series did not converge.");
return term;
}
else //Otherwise just keep recursing
return term*riemannFuncForm(1-s, threshold, ++currSteps, maxSteps);
}
public static double getRiemannSum(double s) {
double threshold = 0.00001;
double currSteps = 1;
int maxSteps = 1000;
return riemannFuncForm(s, threshold, currSteps, maxSteps);
}
// Gamma Function - Lanczos approximation
public static double gamma(double s){
double[] p = {0.99999999999980993, 676.5203681218851, -1259.1392167224028,
771.32342877765313, -176.61502916214059, 12.507343278686905,
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7};
int g = 7;
if(s < 0.5) return Math.PI / (Math.sin(Math.PI * s)*gamma(1-s));
s -= 1;
double a = p[0];
double t = s+g+0.5;
for(int i = 1; i < p.length; i++){
a += p[i]/(s+i);
}
return Math.sqrt(2*Math.PI)*Math.pow(t, s+0.5)*Math.exp(-t)*a;
}
//Binomial Co-efficient
public static double binomial(int n, int k)
{
if (k>n-k)
k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
}
}
I notice that plugging in zeta(-1) returns -
Enter the value of s inside the Riemann Zeta Function: -1
The number of steps is 1.0
Value for the Zeta Function = -0.0506605918211689
Total time taken is 0.0 seconds.
I knew that this value was -1/12. I checked some other values with wolfram alpha and observed that --
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
Returns the correct value. It is just that I am multiplying this value every time by zeta(1-s). In the case of Zeta(1/2), this will always multiply the result by 0.99999999.
Enter the value of s inside the Riemann Zeta Function: 0.5
The series did not converge.
Value for the Zeta Function = 0.999999999999889
Total time taken is 0.006 seconds.
I am going to see if I can replace the part for --
else if (term < threshold) {//The recursion will stop once the term is less than the threshold
System.out.println("The number of steps is " + currSteps);
return term;
}
This difference is the error between two terms in the summation. I may not be thinking about this correctly, it is 1:16am right now. Let me see if I can think better tomorrow ....

What's with this output from a double? [duplicate]

This question already has answers here:
Java: Inaccuracy using double [duplicate]
(4 answers)
Closed 9 years ago.
I am getting strange output when I add doubles together. Can someone tell me why I'm getting repeating decimals when I am adding 0.1 every time?
I have worked out the formula for adding these numbers together and I have done this myself on paper up to 3.3... The sum of all numbers (decreasing by 1 tenth) from 3.3 to 1 equals 51.6
3.3
3.2
3.1 +
3.0
...
1.0
_
51.6
There is an easier way to calculate this using two formulas:
The linear formula for the increasing number: Y = 0.1X + 1
And the sum of increasing numbers formula: [X * (Y + 1)]/2 = total
first solve for Y using any number (in this case 100)
11 = 0.1(100) + 1
Then solve for the total using X and Y
[100 * (11+1)]/2 = 600
The output of the following code should be 600 I believe. There is no question that it should not have a repeating decimal. What am I doing wrong here? There must be something I missed.
public static void main(String[] args) {
int days = 100;
double inc = 0.1;
double init = 1;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}
Double does not have infinite precision (Neither does BigDecimal, but BigDecimal has sufficient precision for this implementation).
Try this,
public static void main(String[] args) {
int days = 100;
java.math.BigDecimal init = java.math.BigDecimal.ONE;
java.math.BigDecimal total = java.math.BigDecimal.ZERO;
java.math.BigDecimal oneTenth = new java.math.BigDecimal(
"0.1");
for (int i = 1; i <= days; i++) {
if (i != 1) {
init = init.add(oneTenth);
}
total = total.add(init);
}
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}
Which outputs
Total: 595.0
Daily: 10.9
Please read the link that Don Roby posted. In essence, double precision is not a good way to represent fractions. A number like 0.1 does not have an exact representation in binary float notation - because floating point numbers are written as "something times two to the power something else". And you cannot solve that exactly for 0.1. Thus, you are really getting a slightly smaller number - actually
0.0999999999999998
And that missing amount is enough to mess up the math…
See Jon Skeet's very excellent answer on this topic: https://stackoverflow.com/a/1089026/1967396
The formula should be
0.1 * (100 * (100 + 1) / 2)
except you start at 10 * 0.1 so the formula is more complicated.
In any case double precision is not exact esp for numbers like 0.1, so you should expect to get rounding error.
You can work around this by using numbers which can be represented accurately like 1 instead of 0.1 (or rounding the result)
public static void main(String... ignored) {
int days = 100;
double inc = 1;
double init = 10;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
total /= 10;
init /= 10;
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}
or round the result.
public static void main(String... ignored) {
int days = 100;
double inc = 0.1;
double init = 1;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
System.out.printf("Total: %.1f%n", total);
System.out.printf("Daily: %.1f%n", init);
}
both print
Total: 595.0
Daily: 10.9

Categories