double formula1, formula2;
int plus;
int VALUE = 10000;
private void processFormula2()
{
for (int k = 0; k <= VALUE; k++) {
if (k % 2 != 0) {
if (plus % 2 == 0) {
double math = 1/k;
formula2 += math;
System.out.println("Getting Formula: "+ formula2);
plus++;
} else {
formula2 -= 1/k;
plus++;
}
// System.out.println("Term: " + formula2);
}
}
}
I am trying to get my formula to print out the result of Pi based off this formula that my teacher gave us. But for some reason it just returns 1.0, not really sure why. Any help or suggestions would be appreciated :)
Here's the problem:
double math = 1/k;
and
formula2 -= 1/k;
k is an int variable, so the JVM won't never return a decimal number in this statement. It will take only two possible values: 0 (if k > 1) or 1 (if k == 1) because the JVM performs the division before promoting the result to double.
Try this:
formula2 -= 1/(double)k;
Take a look at Numeric Promotions
Firstly, there are multiple errors with variable declaration.
double math = 1/k;will not truly work in Java due to how integer division is handled. You must either cast '1' to a double like double math = (double)1/k; or specify that you are using mixed mode arithmetic by using double math = 1.0/k;. This is also a problem for your formula2 variable (Along with you should always initialize your variables like formula1, formula2, and plus). You must also do the same thing with formula2 -= 1/k;.
Secondly, we have no idea what you are setting those variables to in the first place, nor do we have any test cases to compare to.
Related
Edit: This has to do with how computers handle floating point operations, a fact that every programmer faces once in a lifetime. I didn't understand this correctly when I asked the question.
I know the simplest way to start dealing with this would be:
val floatNumber: Float = 123.456f
val decimalPart = floatNumber - floatNumber.toInt() //This would be 0.456 (I don't care about precision as this is not the main objective of my question)
Now in a real world with a pen and a piece of paper, if I want to "convert" the decimal part 0.456 to integer, I just need to multiply 0.456 * 1000, and I get the desired result, which is 456 (an integer number).
Many proposed solutions suggest splitting the number as string and extracting the decimal part this way, but I need the solution to be obtained mathematically, not using strings.
Given a number, with an unknown number of decimals (convert to string and counting chars after . or , is not acceptable), I need to "extract" it's decimal part as an integer using only math.
Read questions like this with no luck:
How to get the decimal part of a float?
How to extract fractional digits of double/BigDecimal
If someone knows a kotlin language solution, it would be great. I will post this question also on the math platform just in case.
How do I get whole and fractional parts from double in JSP/Java?
Update:
Is there a "mathematical" way to "calculate" how many decimals a number has? (It is obvious when you convert to string and count the chars, but I need to avoid using strings) It would be great cause calculating: decimal (0.456) * 10 * number of decimals(3) will produce the desired result.
Update 2
This is not my use-case, but I guess it will clarify the idea:
Suppose you want to calculate a constant(such as PI), and want to return an integer with at most 50 digits of the decimal part of the constant. The constant doesn't have to be necessarily infinite (can be for example 0.5, in which case "5" will be returned)
I would just multiply the fractional number by 10 (or move the decimal point to the right) until it has no fractional part left:
public static long fractionalDigitsLong(BigDecimal value) {
BigDecimal fractional = value.remainder(BigDecimal.ONE);
long digits;
do {
fractional = fractional.movePointRight(1); // or multiply(BigDecimal.TEN)
digits = fractional.longValue();
} while (fractional.compareTo(BigDecimal.valueOf(digits)) != 0);
return digits;
}
Note 1: using BigDecimal to avoid floating point precision problems
Note 2: using compareTo since equals also compares the scale ("0.0" not equals "0.00")
(sure the BigDecimal already knows the size of the fractional part, just the value returned by scale())
Complement:
If using BigDecimal the whole problem can be compressed to:
public static BigInteger fractionalDigits(BigDecimal value) {
return value.remainder(BigDecimal.ONE).stripTrailingZeros().unscaledValue();
}
stripping zeros can be suppressed if desired
I am not sure if it counts against you on this specific problem if you use some String converters with a method(). That is one way to get the proper answer. I know that you stated you couldn't use String, but would you be able to use Strings within a Custom made method? That could get you the answer that you need with precision. Here is the class that could help us convert the number:
class NumConvert{
String theNum;
public NumConvert(String theNum) {
this.theNum = theNum;
}
public int convert() {
String a = String.valueOf(theNum);
String[] b = a.split("\\.");
String b2 = b[1];
int zeros = b2.length();
String num = "1";
for(int x = 0; x < zeros; x++) {
num += "0";
}
float c = Float.parseFloat(theNum);
int multiply = Integer.parseInt(num);
float answer = c - (int)c;
int integerForm = (int)(answer * multiply);
return integerForm;
}
}
Then within your main class:
public class ChapterOneBasics {
public static void main(String[] args) throws java.io.IOException{
NumConvert n = new NumConvert("123.456");
NumConvert q = new NumConvert("123.45600128");
System.out.println(q.convert());
System.out.println(n.convert());
}
}
output:
45600128
456
Float or Double are imprecise, just an approximation - without precision. Hence 12.345 is somewhere between 12.3449... and 12.3450... .
This means that 12.340 cannot be distinghuished from 12.34. The "decimal part" would be 34 divided by 100.
Also 12.01 would have a "decimal part" 1 divided by 100, and too 12.1 would have 1 divided by 10.
So a complete algorith would be (using java):
int[] decimalsAndDivider(double x) {
int decimalPart = 0;
int divider = 1;
final double EPS = 0.001;
for (;;) {
double error = x - (int)x;
if (-EPS < error && error < EPS) {
break;
}
x *= 10;
decimalPart = 10 * decimalPart + ((int)(x + EPS) % 10);
divider *= 10;
}
return new int[] { decimalPart, divider };
}
I posted the below solution yesterday after testing it for a while, and later found that it does not always work due to problems regarding precision of floats, doubles and bigdecimals. My conclusion is that this problem is unsolvable if you want infinite precision:
So I re-post the code just for reference:
fun getDecimalCounter(d: Double): Int {
var temp = d
var tempInt = Math.floor(d)
var counter = 0
while ((temp - tempInt) > 0.0 ) {
temp *= 10
tempInt = Math.floor(temp)
counter++
}
return counter
}
fun main(args: Array <String> ) {
var d = 3.14159
if (d < 0) d = -d
val decimalCounter = getDecimalCounter(d)
val decimalPart = (d - Math.floor(d))
var decimalPartInt = Math.round(decimalPart * 10.0.pow(decimalCounter))
while (decimalPartInt % 10 == 0L) {
decimalPartInt /= 10
}
println(decimalPartInt)
}
I dropped floats because of lesser precision and used doubles.
The final rounding is also necessary due to precision.
A simple comparison of two double values in Java creates some problems. Let's consider the following simple code snippet in Java.
package doublecomparision;
final public class DoubleComparision
{
public static void main(String[] args)
{
double a = 1.000001;
double b = 0.000001;
System.out.println("\n"+((a-b)==1.0));
}
}
The above code appears to return true, the evaluation of the expression ((a-b)==1.0) but it doesn't. It returns false instead because the evaluation of this expression is 0.9999999999999999 which was actually expected to be 1.0 which is not equal to 1.0 hence, the condition evaluates to boolean false. What is the best and suggested way to overcome such a situation?
Basically you shouldn't do exact comparisons, you should do something like this:
double a = 1.000001;
double b = 0.000001;
double c = a-b;
if (Math.abs(c-1.0) <= 0.000001) {...}
Instead of using doubles for decimal arithemetic, please use java.math.BigDecimal. It would produce the expected results.
For reference take a look at this stackoverflow question
You can use Double.compare; It compares the two specified double values.
int mid = 10;
for (double j = 2 * mid; j >= 0; j = j - 0.1) {
if (j == mid) {
System.out.println("Never happens"); // is NOT printed
}
if (Double.compare(j, mid) == 0) {
System.out.println("No way!"); // is NOT printed
}
if (Math.abs(j - mid) < 1e-6) {
System.out.println("Ha!"); // printed
}
}
System.out.println("Gotcha!");
Consider this line of code:
Math.abs(firstDouble - secondDouble) < Double.MIN_NORMAL
It returns whether firstDouble is equal to secondDouble. I'm unsure as to whether or not this would work in your exact case (as Kevin pointed out, performing any math on floating points can lead to imprecise results) however I was having difficulties with comparing two double which were, indeed, equal, and yet using the 'compareTo' method didn't return 0.
I'm just leaving this there in case anyone needs to compare to check if they are indeed equal, and not just similar.
Just use Double.compare() method to compare double values.
Double.compare((d1,d2) == 0)
double d1 = 0.0;
double d2 = 0.0;
System.out.println(Double.compare((d1,d2) == 0)) // true
double a = 1.000001;
double b = 0.000001;
System.out.println( a.compareTo(b) );
Returns:
-1 : 'a' is numerically less than 'b'.
0 : 'a' is equal to 'b'.
1 : 'a' is greater than 'b'.
Link to exercise: mooc.cs.helsinki.fi/programming-part1/material-2013/week-3?noredirect=1#e67
Would this work? I feel like my math is correct, but I can't test my code because I'm at work.
SUM:
int a = 0;
int sum = 0;
while (a < list.size()) {
sum += list.get(a);
a++;
}
return sum;
AVERAGE:
double average = sum(list)/list.size();
return average;
VARIANCE:
int a = 0;
double b = list.get(a) - average(list);
double sum = 0;
while (a < list.size()) {
sum += Math.pow(b, 2);
a++;
}
double variance = sum / (list.size() - 1);
return variance;
Would that work?
FOLLOW UP QUESTION:
This is apparently the "correct" way to do it...
double sumDiffSquared = 0.0;
double avg = average(list);
for (int value : list) {
double difference = value - avg;
difference *= difference;
sumDiffSquared += difference;
double variance = difference / (list.size() - 1);
}
return variance;
Okay so I THINK I understand most of it (notes below)...
double difference = value - avg;
Everything from "list" was put into the variable "value" and now we are subtracting the previously calculated average from each number within the variable "value" one-by-one and putting the new values into the variable "difference". Makes perfect sense.
difference *= difference;
We are now multiplying each number within the variable "difference" by itself. Once again, one-by-one. Makes sense.
Here's where I get lost...
sumDiffSquared += difference
This is what makes no sense to me. Why/how does this add the values together? To me it looks like the value of the variable "sumDiffSquared" is 0, so this would just be adding 0 to each of the values in the variable "difference"...
The variable sumDiffSquared does not get reset for each loop, therefore it is accumulating the value of difference for each loop.
A simple comparison of two double values in Java creates some problems. Let's consider the following simple code snippet in Java.
package doublecomparision;
final public class DoubleComparision
{
public static void main(String[] args)
{
double a = 1.000001;
double b = 0.000001;
System.out.println("\n"+((a-b)==1.0));
}
}
The above code appears to return true, the evaluation of the expression ((a-b)==1.0) but it doesn't. It returns false instead because the evaluation of this expression is 0.9999999999999999 which was actually expected to be 1.0 which is not equal to 1.0 hence, the condition evaluates to boolean false. What is the best and suggested way to overcome such a situation?
Basically you shouldn't do exact comparisons, you should do something like this:
double a = 1.000001;
double b = 0.000001;
double c = a-b;
if (Math.abs(c-1.0) <= 0.000001) {...}
Instead of using doubles for decimal arithemetic, please use java.math.BigDecimal. It would produce the expected results.
For reference take a look at this stackoverflow question
You can use Double.compare; It compares the two specified double values.
int mid = 10;
for (double j = 2 * mid; j >= 0; j = j - 0.1) {
if (j == mid) {
System.out.println("Never happens"); // is NOT printed
}
if (Double.compare(j, mid) == 0) {
System.out.println("No way!"); // is NOT printed
}
if (Math.abs(j - mid) < 1e-6) {
System.out.println("Ha!"); // printed
}
}
System.out.println("Gotcha!");
Consider this line of code:
Math.abs(firstDouble - secondDouble) < Double.MIN_NORMAL
It returns whether firstDouble is equal to secondDouble. I'm unsure as to whether or not this would work in your exact case (as Kevin pointed out, performing any math on floating points can lead to imprecise results) however I was having difficulties with comparing two double which were, indeed, equal, and yet using the 'compareTo' method didn't return 0.
I'm just leaving this there in case anyone needs to compare to check if they are indeed equal, and not just similar.
Just use Double.compare() method to compare double values.
Double.compare((d1,d2) == 0)
double d1 = 0.0;
double d2 = 0.0;
System.out.println(Double.compare((d1,d2) == 0)) // true
double a = 1.000001;
double b = 0.000001;
System.out.println( a.compareTo(b) );
Returns:
-1 : 'a' is numerically less than 'b'.
0 : 'a' is equal to 'b'.
1 : 'a' is greater than 'b'.
I'm trying to take an integer as a parameter and then use recursion to double each digit in the integer.
For example doubleDigit(3487) would return 33448877.
I'm stuck because I can't figure out how I would read each number in the digit I guess.
To do this using recursion, use the modulus operator (%), dividing by 10 each time and accumulating your resulting string backwards, until you reach the base case (0), where there's nothing left to divide by. In the base case, you just return an empty string.
String doubleDigit(Integer digit) {
if (digit == 0) {
return "";
} else {
Integer thisDigit = digit % 10;
Integer remainingDigits = (digit - thisDigit) / 10;
return doubleDigit(remainingDigits) + thisDigit.toString() + thisDigit.toString();
}
}
If you're looking for a solution which returns an long instead of a String, you can use the following solution below (very similar to Chris', with the assumption of 0 as the base case):
long doubleDigit(long amt) {
if (amt == 0) return 0;
return doubleDigit(amt / 10) * 100 + (amt % 10) * 10 + amt % 10;
}
The function is of course limited by the maximum size of a long in Java.
I did the same question when doing Building Java Programs. Here is my solution which works for negative and positive numbers (and returns 0 for 0).
public static int doubleDigits(int n) {
if (n == 0) {
return 0;
} else {
int lastDigit = n % 10;
return 100 * doubleDigits(n / 10) + 10 * lastDigit + lastDigit;
}
There's no need to use recursion here.
I'm no longer a java guy, but an approximation of the algorithm I might use is this (works in C#, should translate directly to java):
int number = 3487;
int output = 0;
int shift = 1;
while (number > 0) {
int digit = number % 10; // get the least-significant digit
output += ((digit*10) + digit) * shift; // double it, shift it, add it to output
number /= 10; // move to the next digit
shift *= 100; // increase the amount we shift by two digits
}
This solution should work, but now that I've gone to the trouble of writing it, I realise that it is probably clearer to just convert the number to a string and manipulate that. Of course, that will be slower, but you almost certainly don't care about such a small speed difference :)
Edit:
Ok, so you have to use recursion. You already accepted a perfectly fine answer, but here's mine :)
private static long DoubleDigit(long input) {
if (input == 0) return 0; // don't recurse forever!
long digit = input % 10; // extract right-most digit
long doubled = (digit * 10) + digit; // "double" it
long remaining = input / 10; // extract the other digits
return doubled + 100*DoubleDigit(remaining); // recurse to get the result
}
Note I switched to long so it works with a few more digits.
You could get the String.valueOf(doubleDigit) representation of the given integer, then work with Commons StringUtils (easiest, in my opinion) to manipulate the String.
If you need to return another numeric value at that point (as opposed to the newly created/manipulated string) you can just do Integer.valueOf(yourString) or something like that.