How to change the sign ("+" "-") every other time in Java - java

I have to wright a function for Newtons approximation of Pi.
Newton calculated that Pi/(2* sqrt(2)) = 1+ 1/3 - 1/5 - 1/7 + 1/9 + 1/11 -...
public class newtonPi {
public static void main(String []args) {
int n = 10;
double piN = 0;
int sign = -1;
for(int i = 1; i < n; i+=2) {
System.out.println("i:"+i+" sign:"+sign);
piN += sign*(1.0/i);
sign *= -1;
}
System.out.println(piN*(2*Math.sqrt(2)));
}}
But with this approach, the sign changes everytime and not every other.
Thanks for the help :)

The pattern repeats every 8. Use the remainder operator % (aka modulo):
sign = n % 8 > 4 ? -1 : 1;

If I understood your question, you want to change the sign every two iterations, right? The problem is you're doing sign *= -1 on each iteration.
Try to use another variable in order to figure out if the sign must be inverted in the current iteration. Here is your code updated:
int sign = 1; // Start with positive
for(int i = 1,iteration = 0; i < n; i += 2,iteration++) {
System.out.println("i:" + i + " sign:" + sign);
piN += sign * (1.0 / i);
if(iteration % 2 != 0){
sign *= -1; // Change every 2 iterations, the odd ones
}
}

Related

Does Java have a limit on loop cycles?

I solved the Project Euler problem #14 https://projecteuler.net/problem=14 on Java, but when I run it in Powershell, it stops iterating at exactly i = 113383 every time. I rewrote the solution on python, and it works perfectly fine, albeit slowly. According to my (identical) python solution, the answer is that the number that produces the longest chain is 837799 and the chain is 524 operations long.
Why does the Java solution not finish the for-loop? Is there some kind of limit in Java on how long it can stay in a loop? I cannot come up with any other explanation. Java code below. I wrote the System.out.println(i) there just to see what is going on.
class ProjectEuler14 {
public static void main(String[] args) {
int largestNumber = 1;
int largestChain = 1;
int currentNumber;
int chainLength;
for (int i = 2; i < 1000000; i++) {
System.out.println(i);
currentNumber = i;
chainLength = 0;
while (currentNumber != 1) {
if (currentNumber % 2 == 0) currentNumber /= 2;
else currentNumber = 3 * currentNumber + 1;
chainLength++;
}
if (chainLength > largestChain) {
largestChain = chainLength;
largestNumber = i;
}
}
System.out.println("\n\nThe number under million that produces the "
+ "longest chain is " + largestNumber +
" and the chain's length is " + largestChain);
}
}
It's not the for loop. It's the while loop. The condition currentNumber != 1 is always true; forever.
In java, an int is specifically defined as an integral number between -2^31 and +2^31 -1, inclusive, and operations 'roll over'. try it!
int x = 2^31 -1;
x++;
System.out.println(x);
this prints a large negative number (in fact, precisely -2^31).
It's happening in your algorithm, and that's why it never finishes.
A trivial solution is to 'upgrade' to longs; they are just as fast, really (yay 64-bit processors!) and use 64 bits, thus giving them a range of -2^63 to +2^63-1.
Python sort of scales up its numbers into slowness silently, java makes different choices (and, for crypto and other purposes, that rollover thing is in fact desired).
If you want to go even further, you can always use BigInteger, which grows as much as you need forever (becoming slower and taking more memory as it goes).
To know rollover occurred, the 3* operation would then result in a number that is lower than the original, and you can check for that:
replace:
else currentNumber = 3 * currentNumber + 1;
with:
else {
int newNumber = currentNumber * 3 + 1;
if (newNumber < currentNumber) throw new IllegalStateException("Overflow has occurred; 3 * " + currentNumber + " + 1 exceeds ints capacities.");
currentNumber = newNumber;
}
and rerun it. You'll see your app nicely explain itself.
The currentNumber is exceeding size of int, use long instead.
Do you hava problem overflow int.
Change int to long.
long largestNumber = 1;
long largestChain = 1;
long currentNumber;
long chainLength;
for (int i = 2; i < 1000000; i++) {
//System.out.println(i);
currentNumber = i;
chainLength = 0;
while (currentNumber != 1) {
//System.out.println("# = " + currentNumber);
if (currentNumber % 2 == 0) {
currentNumber /= 2;
} else {
currentNumber = (3 * currentNumber) +1 ;
}
chainLength++;
}
// System.out.println("################################ " + i);
if (chainLength > largestChain) {
largestChain = chainLength;
largestNumber = i;
}
}
System.out.println("\n\nThe number under million that produces the "
+ "longest chain is " + largestNumber
+ " and the chain's length is " + largestChain);

Write a program that will calculate the number of trailing zeros in a factorial of a given number. N! = 1 * 2 * 3 * ... * N

This is my code for the Codewars problem (Java) yet I cannot make it work. I'm pretty sure I've made a stupid mistake somewhere because of my lack of experience (coding for 4 months)
public static int zeros(int n) {
int f = 1;
int zerocount = 0;
for(int i = 2 ; i <= n; i++){
f *= i;
}
String factorial = String.valueOf(f);
String split [] = factorial.split("");
for(int i = 0; i < split.length; i++){
String m = split[i];
if(m.equals( "0")){
zerocount ++;
}
else {
zerocount = 0;
}
}
return zerocount;
}
}
In fact, you do not need to calculate the factorial because it will rapidly explode into a huge number that will overflow even a long. What you want to do is count the number of fives and twos by which each number between 2 and n can be divided.
static int powersoffive(int n) {
int p=0;
while (n % 5 == 0) {
p++;
n /= 5;
}
return p;
}
static int countzeros(int n) {
int fives = 0;
for (int i = 1; i <= n; i++)
fives += powersoffive(i);
return fives;
}
Note: Lajos Arpad's solution is superior.
As pointed out by other users your solution will probably not be accepted because of the exploding factorial you are calculating.
About the code you wrote there are two mistakes you have made:
You are calculating the factorial in the wrong way. You should start with i = 2 in the loop
for(int i = 2; i <= n; i++){
f *= i;
}
Also in Java you cannot compare strings using ==. This is not valid
if(m == "0")
You should compare them like this
if(m.equals("0"))
Anyway this is how I would have resolved the problem
public static int zeros(int n) {
int zerocount = 0;
for (int i = 5; n / i > 0; i *= 5) {
zerocount += n / i;
}
return zerocount;
}
A zero in a base-10 representation of a number is a 2*5. In order to determine the number of trailing zeroes you will need to determine how many times can you divide your number with ten, or, in other words, the minimum of the sum of 2 and 5 factors. Due to the fact that 5 is bigger than 2 and we go sequentially, the number of fives will be the number of trailing zeroes.
A naive approach would be to round down n/5, but that will only give you the number of items divisible with 5. However, for example, 25 is divisible by 5 twice. The same can be said about 50. 125 can be divided by 5 three times, no less.
So, the algorithm would look like this:
int items = 0;
int power = 5;
while (power < n) {
items += (int) (n / power);
power *= 5;
}
Here small numbers are in use in relative terms, but it's only a proof of concept.
You do need to use brute force here and you integers will overflow anyway.
With multiplication trailing zero appears only as the result of 2*5.
Now imagine the factorial represented by a product of it's prime factors.
Notice that for every 5 (five) we will always have 2 (two).
So to calculate the number of zeroes we need to calculate the number of fives.
That can be implemented by continuously dividing N by five and totaling results
In Java code that will be something like this:
static int calculate(int n)
{
int result = 0;
while (n > 0 ) {
n /= 5;
result += n;
}
return result;
}

Is there any better algorithm to do this? (Unit fractions creation)

I have been given a problem where fractions between 1/2 - 1/1000 have to be added to create the longest sequence of all unique unit fractions.
The rules on constructing these fractions:
Let create a set: D , D is only to hold unique unit fractions , sub-fractions can add up to the same fraction for example:
1/10
/ \
1/110 + 1/11 1/35 + 1/14
All sub-fractions can be held within the set as long as they themselves are not the same fractions once we are adding them together it is ok for them to total up to the same root.
The goal:
The fractions have to be added in a way to sum up to exactly 1. Any sub-fractions are not allowed to be over 1000 it is explicitly between 2 and 1000 hence the fractions which make up 1/1000 would not be applicable ( 1/1004 + 1/251000 ).
What currently I found to be the most effective:
Find the two lowest multiples which make-up the current fraction that I am looking at so for e.g 1/6 = A = 3 , B = 2. And now we complete the following equation: C = (A+B)*A , D = (A+B)*B. Now C & D are the sub-fractions which add up to my initial fraction
1/6
/ \
1/15 1/10
In code:
public static int[] provideFactorsSmallest(int n) {
int k[] = new int[2];
for(int i = 2; i <= n - 1; i++) {
if(n % i == 0) {
k[0] = i;
break;
}
}
for(int i = k[0] + 1; i <= n - 1 && k[0] != 0; i++) {
//System.out.println("I HAVE BEEN ENTERED");
if(k[0] * i == n) {
k[1] = i;
int firstTerm = k[0];
int secondTerm = k[1];
k[0] = (firstTerm + secondTerm) * firstTerm;
k[1] = (firstTerm + secondTerm) * secondTerm;
return k;
}
}
return null;
}
My question:
What would be the most effective way to pair and group the numbers to achieve possible longest fraction sequence?
Thank you in advance!

How to convert a decimal to binary using for loops?

/* This program converts decimal to binary */
import javax.swing.JOptionPane;
public class BinaryLoop {
public static void main(String []args) {
String askForDecimal = JOptionPane.showInputDialog("Enter the decimal number you would like to convert?");
int decimalNumber = Integer.parseInt(askForDecimal);
int remainder = 0;
for (int i = 1; decimalNumber > 0; i++) {
decimalNumber /= 2;
remainder = decimalNumber % 2;
System.out.print(remainder);
}
}
}
For example I type in 15 but it returns 1110 which should be 1111.
p.s. this the result will be read from right to left.
decimalNumber /= 2;
remainder = decimalNumber % 2;
These two lines should be in the opposite order. Can you see why?
You don't need the variable i in your for loop at all, just use a while loop.
There is a flaw in your algorithm because you are dividing first:
15 / 2 = 7
7 / 2 = 3
3 / 2 = 1
1 / 2 = 0
You need to check the remainder before dividing, not afterwards.
If you understand the intent of the program, you should see the problem if you output some of the intermediate workings:
int remainder = 0;
for (int i = 1; decimalNumber > 0; i++) {
System.out.println("Entering for() block");
System.out.println("decimalNumber=" + decimalNumber);
decimalNumber /= 2;
System.out.println("decimalNumber=" + decimalNumber);
remainder = decimalNumber % 2;
System.out.println(remainder);
}
}
Examine the output of this and the error should become obvious, which is that because two statements are the wrong way around, you're missing the first, biggest, value of decimalNumber.
You might also notice that remainder is not used outside the block, so you don't need to declare it outside the block, and you don't need to initialise it to zero.
Likewise, you might notice that the value of i is never used, so you could change the for loop to:
for(;decimalNumber > 0;)
... which is equivalent to:
while(decimalNumber > 0)
Many people get into the habit of putting temporary println statements in their code to debug. However it's a bad habit. Instead, learn to use a debugger as soon as you can. With a debugger you can pause a program and step through it line by line, looking at the values of all the variables as they change.
You need to do this:
String s = "";
Integer remainder = 0;
while(decimalNumber > 0) {
remainder = decimalNumber % 2;
decimalNumber /= 2;
s = remainder.toString() + s;
}
System.out.println(s);
you have to change the code to
remainder = decimalNumber % 2;
decimalNumber /= 2;
You have to get the remainder before dividing the number by 2.

Check if string is following ISBN-13 in Java

Im trying to check if a string (important that it is a string) that im reading is correct accoring to the rules of ISBN-13. I found a formula
For example, the ISBN-13 check digit of 978-0-306-40615-?
is calculated as follows:
s = 9×1 + 7×3 + 8×1 + 0×3 + 3×1 + 0×3 + 6×1 + 4×3 + 0×1 + 6×3 + 1×1 + 5×3
= 9 + 21 + 8 + 0 + 3 + 0 + 6 + 12 + 0 + 18 + 1 + 15
= 93
93 / 10 = 9 remainder 3
10 – 3 = 7`
My problem is i don't know how to multiply one number with 1 and every other with 3 ? Im guessing a for-loop but i don't know how to start.
You could "simply" use regular expressions:
ISBN(-1(?:(0)|3))?:?\x20+(?(1)(?(2)(?:(?=.{13}$)\d{1,5}([ -])\d{1,7}\3\d{1,6}\3(?:\d|x)$)|(?:(?=.{17}$)97(?:8|9)([ -])\d{1,5}\4\d{1,7}\4\d{1,6}\4\d$))|(?(.{13}$)(?:\d{1,5}([ -])\d{1,7}\5\d{1,6}\5(?:\d|x)$)|(?:(?=.{17}$)97(?:8|9)([ -])\d{1,5}\6\d{1,7}\6\d{1,6}\6\d$)))
You have 6 pairs of (even,odd) numbers, so go through them pairwise.
for (i = 0; i < 6; i++) {
even += array[2*i];
odd += array[2*i+1]*3;
}
checkbit = 10 - (even+odd)%10;
assuming your inputString is ascii:
int odd = 0;
int even = 0;
char[] c = (inputString + "00").replaceAll("[\\-]", "").toCharArray();
for (int i = 0; i < (c.length - 1) / 2; ++i) {
odd += c[2 * i] - 48;
even += c[2 * i + 1] - 48;
}
int result = 10 - (odd + 3 * even) % 10;
This seems to work effectively and is clear.
// Calculates the isbn13 check digit for the 1st 12 digits in the string.
private char isbn13CheckDigit(String str) {
// Sum of the 12 digits.
int sum = 0;
// Digits counted.
int digits = 0;
// Start multiplier at 1. Alternates between 1 and 3.
int multiplier = 1;
// Treat just the 1st 12 digits of the string.
for (int i = 0; i < str.length() && digits < 12; i++) {
// Pull out that character.
char c = str.charAt(i);
// Is it a digit?
if ('0' <= c && c <= '9') {
// Keep the sum.
sum += multiplier * (c - '0');
// Flip multiplier between 1 and 3 by flipping the 2^1 bit.
multiplier ^= 2;
// Count the digits.
digits += 1;
}
}
// What is the check digit?
int checkDigit = (10 - (sum % 10)) % 10;
// Give it back to them in character form.
return (char) (checkDigit + '0');
}
NB: Edited to correctly handle the 0 check digit. See Wikipedia International Standard Book Number for example isbn with check digit of 0.
Paul
Similar, with loop and awful char-to-string-to-int conversions ;]
boolean isISBN13(String s){
String ss = s.replaceAll("[^\\d]", "");
if(ss.length()!=13)
return false;
int sum=0, multi=1;
for(int i=0; i<ss.length()-1; ++i){
sum += multi * Integer.parseInt(String.valueOf(ss.charAt(i)));
multi = (multi+2)%4; //1 or 3
}
return (Integer.parseInt(String.valueOf(ss.charAt(ss.length()))) == (10 - sum%10));
}

Categories