Check if BigInteger is not a perfect square - java

I have a BigInteger value, let's say it is 282 and is inside the variable x. I now want to write a while loop that states:
while b2 isn't a perfect square:
a ← a + 1
b2 ← a*a - N
endwhile
How would I do such a thing using BigInteger?
EDIT: The purpose for this is so I can write this method. As the article states one must check if b2 is not square.

Compute the integer square root, then check that its square is your number. Here is my method of computing the square root using Heron's method:
private static final BigInteger TWO = BigInteger.valueOf(2);
/**
* Computes the integer square root of a number.
*
* #param n The number.
*
* #return The integer square root, i.e. the largest number whose square
* doesn't exceed n.
*/
public static BigInteger sqrt(BigInteger n)
{
if (n.signum() >= 0)
{
final int bitLength = n.bitLength();
BigInteger root = BigInteger.ONE.shiftLeft(bitLength / 2);
while (!isSqrt(n, root))
{
root = root.add(n.divide(root)).divide(TWO);
}
return root;
}
else
{
throw new ArithmeticException("square root of negative number");
}
}
private static boolean isSqrt(BigInteger n, BigInteger root)
{
final BigInteger lowerBound = root.pow(2);
final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
return lowerBound.compareTo(n) <= 0
&& n.compareTo(upperBound) < 0;
}

I found a sqrt method used here, and simplified the square test.
private static final BigInteger b100 = new BigInteger("100");
private static final boolean[] isSquareResidue;
static{
isSquareResidue = new boolean[100];
for(int i =0;i<100;i++){
isSquareResidue[(i*i)%100]=true;
}
}
public static boolean isSquare(final BigInteger r) {
final int y = (int) r.mod(b100).longValue();
boolean check = false;
if (isSquareResidue[y]) {
final BigInteger temp = sqrt(r);
if (r.compareTo(temp.pow(2)) == 0) {
check = true;
}
}
return check;
}
public static BigInteger sqrt(final BigInteger val) {
final BigInteger two = BigInteger.valueOf(2);
BigInteger a = BigInteger.ONE.shiftLeft(val.bitLength() / 2);
BigInteger b;
do {
b = val.divide(a);
a = (a.add(b)).divide(two);
} while (a.subtract(b).abs().compareTo(two) >= 0);
return a;
}

public static Boolean PerfectSQR(BigInteger A){BigInteger B=A.sqrt(), C=B.multiply(B);return (C.equals(A));}

DON'T use this...
BigInteger n = ...;
double n_as_double = n.doubleValue();
double n_sqrt = Math.sqrt(n_as_double);
BigInteger n_sqrt_as_int = new BigDecimal(n_sqrt).toBigInteger();
if (n_sqrt_as_int.pow(2).equals(n)) {
// number is perfect square
}
As Christian Semrau commented below - this doesn't work. I am sorry for posting incorrect answer.

using System.Numerics; // needed for BigInteger
/* Variables */
BigInteger a, b, b2, n, p, q;
int flag;
/* Assign Data */
n = 10147;
a = iSqrt(n);
/* Algorithm */
do
{ a = a + 1;
b2 = (a * a) – n;
b = iSqrt(b2);
flag = BigInteger.Compare(b * b, b2);
} while(flag != 0);
/* Output Data */
p = a + b;
q = a – b;
/* Method */
private static BigInteger iSqrt(BigInteger num)
{ // Finds the integer square root of a positive number
if (0 == num) { return 0; } // Avoid zero divide
BigInteger n = (num / 2) + 1; // Initial estimate, never low
BigInteger n1 = (n + (num / n)) / 2;
while (n1 < n)
{ n = n1;
n1 = (n + (num / n)) / 2;
}
return n;
} // end iSqrt()

private static boolean isSqrt(BigInteger n, BigInteger root)
{
final BigInteger lowerBound = root.pow(2);
final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
return lowerBound.compareTo(n) <= 0
&& n.compareTo(upperBound) < 0;
}
I tried the above using JavaScript BigInt:
function isPerfectSqrt(n, root) {
const lowerBound = root**2n;
const upperBound = (root+1n)**2n
return lowerBound <= n && n < upperBound;
}
And found it was only about 60% as fast (in Node V8) as the one-liner:
function isPerfectSqrt(n, root) {
return (n/root === root && n%root === 0n)
}

The number you want to do a perfect square test on is A. B is the integer square root of A and the .sqrt() function returns the integer lower floor of the square root. The Boolean of B*B=A is returned. The Boolean return is "true" if it is a perfect square and "false" if it is not a perfect square.
public static Boolean PerfectSQR(BigInteger A) {
BigInteger B = A.sqrt();
return B.multiply(B).equals(A);
}
An alternative is to use the sqrtAndRemainder() function. If the remainder, B[1], is zero it is a perfect square. The boolean TRUE then is returned as shown below.
public static Boolean PerfectSQR(BigInteger A) {
BigInteger [] B=A.sqrtAndRemainder();
return B[1].equals(BigInteger.ZERO);
}

Related

Fibonacci sequence - How to calculate the sum of the first 100 even-values Fibonacci numbers?

Fibonacci sequence is defined as a sequence of integers starting with 1 and 1, where each subsequent value is the sum of the preceding two I.e.
f(0) = 1
f(1) = 1
f(n) = f(n-1) + f(n-2) where n>=2
My goal is to calculate the sum of the first 100 even-values Fibonacci numbers.
So far I've found this code which works perfectly to calculate the sum of even numbers to 4million , however I'm unable to find edit the code so that it stops at the sum of the 100th value, rather than reaching 4million.
public class Improvement {
public static int Fibonacci(int j) {
/**
*
* Recursive took a long time so continued with iterative
*
* Complexity is n squared.. try to improve to just n
*
*/
int tmp;
int a = 2;
int b = 1;
int total = 0;
do {
if(isEven(a)) total +=a;
tmp = a + b;
b = a;
a = tmp;
} while (a < j);
return total;
}
private static boolean isEven(int a) {
return (a & 1) == 0;
}
public static void main(String[] args) {
// Notice there is no more loop here
System.out.println(Fibonacci(4_000_000));
}
}
Just to show the console from #mr1554 code answer, the first 100 even values are shown and then the sum of all is 4850741640 as can be seen below:
Any help is appreciated, thanks!
You need to use BigInteger because long easily overflows as Fibonacci's scales quite easily. BigInteger is also tricky to check whether is an odd or even number, but you can use BigInteger::testBit returning boolean as explained in this answer.
Here is some complete code:
BigInteger fibonacciSum(int count, boolean isOdd) {
int i = 0;
BigInteger sum = BigInteger.ZERO;
BigInteger current = BigInteger.ONE;
BigInteger next = BigInteger.ONE;
BigInteger temp;
while (i < count) {
temp = current;
current = current.add(next);
next = temp;
if ((current.testBit(0) && isOdd) || ((!current.testBit(0) && !isOdd))) {
sum = sum.add(current);
i++;
}
}
return sum;
}
Or you can have some fun with Stream API:
BigInteger fibonacciSum(int count, boolean isOdd) {
final BigInteger[] firstSecond = new BigInteger[] {BigInteger.ONE, BigInteger.ONE};
return Stream.iterate(
firstSecond,
num -> new BigInteger[] { num[1], num[0].add(num[1]) })
.filter(pair ->
(pair[1].testBit(0) && isOdd) ||
(!pair[1].testBit(0) && !isOdd))
.limit(count)
.map(pair -> pair[1])
.reduce(BigInteger.ZERO, BigInteger::add);
}
In any way, don't forget to test it out:
#Test
void test() {
assertThat(
fibonacciSum(100, false),
is(new BigInteger("290905784918002003245752779317049533129517076702883498623284700")));
}
You said.
My goal is to calculate the sum of the first 100 even-values Fibonacci numbers.
That number gets very large very quickly. You need to:
use BigInteger
use the mod function to determine if even
For this I could have started from (1,1) but it's only one term so ...
BigInteger m = BigInteger.ZERO;
BigInteger n = BigInteger.ONE;
BigInteger sumOfEven= BigInteger.ZERO;
int count = 0;
BigInteger t;
while( count < 100) {
t = n.add(m);
// check if even
if (t.mod(BigInteger.TWO).equals(BigInteger.ZERO)) {
sumOfEven = sumOfEven.add(t);
count++;
}
n = m;
m = t;
}
System.out.println(sumOfEven);
Prints
290905784918002003245752779317049533129517076702883498623284700
If, on the other hand, from your comment.
My aim is to calculate the sum of the first 100 even numbers
Then you can do that like so
sumFirstNeven = (((2N + 2)N)/2 = (N+1)N
so (101)100 = 10100 and the complexity is O(1)
as I figured, you want a program to sum 100 first even values of the Fibonacci series.
here is a sample code, when you run the program it will ask you to determine the number of the even values, you want 100 value e.g, type 100 in consul:
public static void main(String[] args) {
int firstNumber = 0;
int secondNumber = 2;
System.out.print("Enter the number of odd elements of the Fibonacci Series to sum : ");
Scanner scan = new Scanner(System.in);
int elementCount = scan.nextInt(); // number of even values you want
System.out.print(firstNumber + ", ");
System.out.print(secondNumber + ", ");
long sum = 2;
for (int i = 2; i < elementCount; i++) {
int nextNumber = firstNumber + secondNumber;
System.out.print(nextNumber + ", ");
sum += (nextNumber);
firstNumber = secondNumber;
secondNumber = nextNumber;
}
System.out.print("...");
System.out.println("\n" + "the sum of " + elementCount + " values of fibonacci series is: " + sum);
}

Calculating the product of BigInteger[]

Context: I'm trying to calculate factorials for very large n using the BigInteger class in Java (for n>100,000) and so far this what I'm doing:
Produce all primes less than or equal to n using Sieve of Erasthones
Find to which powers they will be raised.
Raise all the numbers to the respective powers.
Use a divide and conquer recursive method to multiply them all.
From the research I've done on the internet, this is asymptotically faster than simply multiplying all k up to n. However I've noticed that the slowest part of my implementation is the part where I multiply all the prime powers. My questions are:
Is there a faster way to calculate the product of lots of numbers?
Can my implementation be improved ?
Code:
public static BigInteger product(BigInteger[] numbers) {
if (numbers.length == 0)
throw new ArithmeticException("There is nothing to multiply!");
if (numbers.length == 1)
return numbers[0];
if (numbers.length == 2)
return numbers[0].multiply(numbers[1]);
BigInteger[] part1 = new BigInteger[numbers.length / 2];
BigInteger[] part2 = new BigInteger[numbers.length - numbers.length / 2];
System.arraycopy(numbers, 0, part1, 0, numbers.length / 2);
System.arraycopy(numbers, numbers.length / 2, part2, 0, numbers.length - numbers.length / 2);
return product(part1).multiply(product(part2));
}
Note that BigInteger uses the karatsuba algorithm for multiplication.
I know that there are lots of questions about calculating factorials. But mine is about calculating the product of BigIntegers for which there is not much resource. (I've seen someone say "Use Divide and Conquer method", but I don't remember where, and I haven't seen any implementation around.
One way to improve the performance is to do the following:
Sort your array of numbers you need to multiply together
Create two new lists: a and b.
For each number in the input list that you need to multiply, it is likely to appear more than once. Let's say number v_i appears n_i times. Then add v_i to the a n_i / 2 times (rounded down). If n_i is odd, add v_i once to b as well.
To compute the result, do:
BigInteger A = product(a);
BigInteger B = prudoct(b);
return a.multiply(a).multiply(b);
To see how it works, consider your input array is [2, 2, 2, 2, 3, 3, 3]. So, there are four 2s and three 3s. Arrays a and b will correspondingly be
a = [2, 2, 3]
b = [3]
Then you will recursively call to compute the product of these. Note that we reduced the number of numbers that we want to multiply from 7 to 4, almost by a factor of two. The trick here is that for numbers that occur many times, we can compute the product of only half of them, and then raise it to the power of two. Very similar to how the power of a number can be computed in O(log n) time.
I propose another idea, the pow algorithm is very fast, you can compute the all primes with the exponent, like this:
11! -> {2^10, 3^5, 5^2, 7^1, 11^1}
You can compute all primes power , and then use divide and conquer to multiply all of them.
The implementation:
private static BigInteger divideAndConquer(List<BigInteger> primesExp, int min, int max){
BigInteger result = BigInteger.ONE;
if (max - min == 1){
result = primesExp.get(min);
} else if (min < max){
int middle = (max + min)/2;
result = divideAndConquer(primesExp, min, middle).multiply(divideAndConquer(primesExp, middle, max));
}
return result;
}
public static BigInteger factorial(int n) {
// compute pairs: prime, exp
List<Integer> primes = new ArrayList<>();
Map<Integer, Integer> primeTimes = new LinkedHashMap<>();
for (int i = 2; i <= n; i++) {
int sqrt = Math.round((float) Math.sqrt(i));
int value = i;
Iterator<Integer> it = primes.iterator();
int prime = 0;
while (it.hasNext() && prime <= sqrt && value != 0) {
prime = it.next();
int times = 0;
while (value % prime == 0) {
value /= prime;
times++;
}
if (times > 0) {
primeTimes.put(prime, times + primeTimes.get(prime));
}
}
if (value > 1) {
Integer times = primeTimes.get(value);
if (times == null) {
times = 0;
primes.add(value);
}
primeTimes.put(value, times + 1);
}
}
// compute primes power:
List<BigInteger> primePows = new ArrayList<>(primes.size());
for (Entry<Integer,Integer> e: primeTimes.entrySet()) {
primePows.add(new BigInteger(String.valueOf(e.getKey())).pow(e.getValue()));
}
// it multiply all of them:
return divideAndConquer(primePows, 0, primePows.size());
}
Probably the fastest approach :
Sequence.java
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class Sequence {
private final List<BigInteger> elements;
private Sequence(List<BigInteger> elements) {
this.elements = elements;
}
public List<BigInteger> getElements() {
return elements;
}
public int size() {
return elements.size();
}
public Sequence subSequence(int startInclusive, int endExclusive) {
return subSequence(startInclusive, endExclusive, false);
}
public Sequence subSequence(int startInclusive, int endExclusive, boolean sync) {
return Sequence.of(elements.subList(startInclusive, endExclusive), sync);
}
public void addLast(BigInteger element) {
elements.add(element);
}
public BigInteger removeLast() {
return elements.remove(size() - 1);
}
public BigInteger sum() {
return sum(false);
}
public BigInteger sum(boolean parallel) {
return parallel
? elements.parallelStream().reduce(BigInteger.ZERO, BigInteger::add)
: elements.stream().reduce(BigInteger.ZERO, BigInteger::add);
}
public BigInteger product() {
return product(false);
}
public BigInteger product(boolean parallel) {
return parallel
? elements.parallelStream().reduce(BigInteger.ONE, BigInteger::multiply)
: elements.stream().reduce(BigInteger.ONE, BigInteger::multiply);
}
public static Sequence range(int startInclusive, int endExclusive) {
return range(startInclusive, endExclusive, false);
}
public static Sequence range(int startInclusive, int endExclusive, boolean sync) {
if (startInclusive > endExclusive) {
throw new IllegalArgumentException();
}
final List<BigInteger> elements = sync ? Collections.synchronizedList(new ArrayList<>()) : new ArrayList<>();
for (; startInclusive < endExclusive; startInclusive++) {
elements.add(BigInteger.valueOf(startInclusive));
}
return new Sequence(elements);
}
public static Sequence of(List<BigInteger> elements) {
return of(elements, false);
}
public static Sequence of(List<BigInteger> elements, boolean sync) {
return new Sequence(sync ? Collections.synchronizedList(elements) : elements);
}
public static Sequence empty() {
return empty(false);
}
public static Sequence empty(boolean sync) {
return of(new ArrayList<>(), sync);
}
}
FactorialCalculator.java
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
public final class FactorialCalculator {
private static final int CHUNK_SIZE = Runtime.getRuntime().availableProcessors();
public static BigInteger fact(int n) {
return fact(n, false);
}
public static BigInteger fact(int n, boolean parallel) {
if (n < 0) {
throw new IllegalArgumentException();
}
if (n <= 1) {
return BigInteger.ONE;
}
Sequence sequence = Sequence.range(1, n + 1);
if (!parallel) {
return sequence.product();
}
sequence = parallelCalculate(splitSequence(sequence, CHUNK_SIZE * 2));
while (sequence.size() > CHUNK_SIZE) {
sequence = parallelCalculate(splitSequence(sequence, CHUNK_SIZE));
}
return sequence.product(true);
}
private static List<Sequence> splitSequence(Sequence sequence, int chunkSize) {
final int size = sequence.size();
final List<Sequence> subSequences = new LinkedList<>();
int index = 0, targetIndex;
while (index < size) {
targetIndex = Math.min(index + chunkSize, size);
subSequences.add(sequence.subSequence(index, targetIndex, true));
index = targetIndex;
}
return subSequences;
}
private static Sequence parallelCalculate(List<Sequence> sequences) {
final Sequence result = Sequence.empty(true);
sequences.parallelStream().map(s -> s.product(true)).forEach(result::addLast);
return result;
}
}
Test :
public static void main(String[] args) {
// warm up
for (int i = 0; i < 100; i++) {
FactorialCalculator.fact(10000);
}
int n = 1000000;
long start = System.currentTimeMillis();
FactorialCalculator.fact(n, true);
long end = System.currentTimeMillis();
System.out.printf("Execution time = %d ms", end - start);
}
Result :
Execution time = 3066 ms
OS : Win 10 Pro 64-bit
CPU : Intel Core i7-4700HQ # 2.40GHz 2.40GHz

Java Fermat Factorisation algorithm BigInteger not working

I'm implementing Fermat Factorization algorithm using BigInteger so I can factor. But at the moment, the code is not working; it hangs for some reason. Could someone direct me to where the issue is, or let me know if my algorithm is incorrect? BigInteger makes life difficult, so I had to look for a square root method.
import java.math.BigInteger;
import java.util.Scanner;
public class Fermat
{
/** Fermat factor **/
public void FermatFactor(BigInteger N)
{
BigInteger a = sqrt(N);
BigInteger b2 = a.multiply(a).subtract(N);
while (!isSquare(b2)) {
a = a.add(a);
b2 = a.multiply(a).subtract(N);
}
BigInteger r1 = a.subtract(sqrt(b2));
BigInteger r2 = N.divide(r1);
display(r1, r2);
}
/** function to display roots **/
public void display(BigInteger r1, BigInteger r2) {
System.out.println("\nRoots = "+ r1 +" , "+ r2);
}
/** function to check if N is a perfect square or not **/
public boolean isSquare(BigInteger N) {
BigInteger ONE = new BigInteger("1");
BigInteger sqr = sqrt(N);
if (sqr.multiply(sqr) == N || (sqr.add(ONE)).multiply(sqr.add(ONE)) == N)
return true;
return false;
}
public static BigInteger sqrt(BigInteger x)
throws IllegalArgumentException {
if (x.compareTo(BigInteger.ZERO) < 0) {
throw new IllegalArgumentException("Negative argument.");
}
// square roots of 0 and 1 are trivial and
// y == 0 will cause a divide-by-zero exception
if (x == BigInteger.ZERO || x == BigInteger.ONE) {
return x;
} // end if
BigInteger two = BigInteger.valueOf(2L);
BigInteger y;
// starting with y = x / 2 avoids magnitude issues with x squared
for (y = x.divide(two);
y.compareTo(x.divide(y)) > 0;
y = ((x.divide(y)).add(y)).divide(two));
if (x.compareTo(y.multiply(y)) == 0) {
return y;
} else {
return y.add(BigInteger.ONE);
}
} // end bigIntSqRootCeil
/** main method **/
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("Fermat Factorization Test\n");
System.out.println("Enter odd number");
BigInteger N = scan.nextBigInteger();
Fermat ff = new Fermat();
ff.FermatFactor(N);
scan.close();
}
}
I know I have a lot of mistakes, but any help is appreciated. Thanks.
Your "for" loop :
for (y = x.divide(two);
y.compareTo(x.divide(y)) > 0;
y = ((x.divide(y)).add(y)).divide(two));
does not terminate. Perhaps you could keep track of the values of the variable 'y', to guess when you have to stop.
Edit : that was wrong (see comments). The problem is in the line
a = a.add(a)
inside procedure FermatFactor. It should rather be
a = a.add(ONE)
In my machine I also had troubles with testing equalities using 'A == B'. The method 'A.equals(B)' fixed it.

Java: simplest integer hash

I need a quick hash function for integers:
int hash(int n) { return ...; }
Is there something that exists already in Java?
The minimal properties that I need are:
hash(n) & 1 does not appear periodic when used with a bunch of consecutive values of n.
hash(n) & 1 is approximately equally likely to be 0 or 1.
HashMap, as well as Guava's hash-based utilities, use the following method on hashCode() results to improve bit distributions and defend against weaker hash functions:
/*
* This method was written by Doug Lea with assistance from members of JCP
* JSR-166 Expert Group and released to the public domain, as explained at
* http://creativecommons.org/licenses/publicdomain
*
* As of 2010/06/11, this method is identical to the (package private) hash
* method in OpenJDK 7's java.util.HashMap class.
*/
static int smear(int hashCode) {
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);
}
So, I read this question, thought hmm this is a pretty math-y question, it's probably out of my league. Then, I ended up spending so much time thinking about it that I actually believe I've got the answer: No function can satisfy the criteria that f(n) & 1 is non-periodic for consecutive values of n.
Hopefully someone will tell me how ridiculous my reasoning is, but until then I believe it's correct.
Here goes: Any binary integer n can be represented as either 1...0 or 1...1, and only the least significant bit of that bitmap will affect the result of n & 1. Further, the next consecutive integer n + 1 will always contain the opposite least significant bit. So, clearly any series of consecutive integers will exhibit a period of 2 when passed to the function n & 1. So then, is there any function f(n) that will sufficiently distribute the series of consecutive integers such that periodicity is eliminated?
Any function f(n) = n + c fails, as c must end in either 0 or 1, so the LSB will either flip or stay the same depending on the constant chosen.
The above also eliminates subtraction for all trivial cases, but I have not taken the time to analyze the carry behavior yet, so there may be a crack here.
Any function f(n) = c*n fails, as the LSB will always be 0 if c ends in 0 and always be equal to the LSB of n if c ends in 1.
Any function f(n) = n^c fails, by similar reasoning. A power function would always have the same LSB as n.
Any function f(n) = c^n fails, for the same reason.
Division and modulus were a bit less intuitive to me, but basically, the LSB of either option ends up being determined by a subtraction (already ruled out). The modulus will also obviously have a period equal to the divisor.
Unfortunately, I don't have the rigor necessary to prove this, but I believe any combination of the above operations will ultimately fail as well. This leads me to believe that we can rule out any transcendental function, because these are implemented with polynomials (Taylor series? not a terminology guy).
Finally, I held out hope on the train ride home that counting the bits would work; however, this is actually a periodic function as well. The way I thought about it was, imagine taking the sum of the digits of any decimal number. That sum obviously would run from 0 through 9, then drop to 1, run from 1 to 10, then drop to 2... It has a period, the range just keeps shifting higher the higher we count. We can actually do the same thing for the sum of the binary digits, in which case we get something like: 0,1,1,2,2,....5,5,6,6,7,7,8,8....
Did I leave anything out?
TL;DR I don't think your question has an answer.
[SO decided to convert my "trivial answer" to comment. Trying to add little text to it to see if it can be fooled]
Unless you need the ranger of hashing function to be wider..
The NumberOfSetBits function seems to vary quite a lot more then the hashCode, and as such seems more appropriate for your needs. Turns out there is already a fairly efficient algorithm on SO.
See Best algorithm to count the number of set bits in a 32-bit integer.
I did some experimentation (see test program below); computation of 2^n in Galois fields, and floor(A*sin(n)) both did very well to produce a sequence of "random" bits. I tried multiplicative congruential random number generators and some algebra and CRC (which is analogous of k*n in Galois fields), none of which did well.
The floor(A*sin(n)) approach is the simplest and quickest; the 2^n calculation in GF32 takes approx 64 multiplies and 1024 XORs worstcase, but the periodicity of output bits is extremely well-understood in the context of linear-feedback shift registers.
package com.example.math;
public class QuickHash {
interface Hasher
{
public int hash(int n);
}
static class MultiplicativeHasher1 implements Hasher
{
/* multiplicative random number generator
* from L'Ecuyer is x[n+1] = 1223106847 x[n] mod (2^32-5)
* http://dimsboiv.uqac.ca/Cours/C2012/8INF802_Hiv12/ref/paper/RNG/TableLecuyer.pdf
*/
final static long a = 1223106847L;
final static long m = (1L << 32)-5;
/*
* iterative step towards computing mod m
* (j*(2^32)+k) mod (2^32-5)
* = (j*(2^32-5)+j*5+k) mod (2^32-5)
* = (j*5+k) mod (2^32-5)
* repeat twice to get a number between 0 and 2^31+24
*/
private long quickmod(long x)
{
long j = x >>> 32;
long k = x & 0xffffffffL;
return j*5+k;
}
// treat n as unsigned before computation
#Override public int hash(int n) {
long h = a*(n&0xffffffffL);
long h2 = quickmod(quickmod(h));
return (int) (h2 >= m ? (h2-m) : h2);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
/**
* computes (2^n) mod P where P is the polynomial in GF2
* with coefficients 2^(k+1) represented by the bits k=31:0 in "poly";
* coefficient 2^0 is always 1
*/
static class GF32Hasher implements Hasher
{
static final public GF32Hasher CRC32 = new GF32Hasher(0x82608EDB, 32);
final private int poly;
final private int ofs;
public GF32Hasher(int poly, int ofs) {
this.ofs = ofs;
this.poly = poly;
}
static private long uint(int x) { return x&0xffffffffL; }
// modulo GF2 via repeated subtraction
int mod(long n) {
long rem = n;
long q = uint(this.poly);
q = (q << 32) | (1L << 31);
long bitmask = 1L << 63;
for (int i = 0; i < 32; ++i, bitmask >>>= 1, q >>>= 1)
{
if ((rem & bitmask) != 0)
rem ^= q;
}
return (int) rem;
}
int mul(int x, int y)
{
return mod(uint(x)*uint(y));
}
int pow2(int n) {
// compute 2^n mod P using repeated squaring
int y = 1;
int x = 2;
while (n > 0)
{
if ((n&1) != 0)
y = mul(y,x);
x = mul(x,x);
n = n >>> 1;
}
return y;
}
#Override public int hash(int n) {
return pow2(n+this.ofs);
}
#Override public String toString() {
return String.format("GF32[%08x, ofs=%d]", this.poly, this.ofs);
}
}
static class QuickHasher implements Hasher
{
#Override public int hash(int n) {
return (int) ((131111L*n)^n^(1973*n)%7919);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
// adapted from http://www.w3.org/TR/PNG-CRCAppendix.html
static class CRC32TableHasher implements Hasher
{
final private int table[];
static final private int polyval = 0xedb88320;
public CRC32TableHasher()
{
this.table = make_table();
}
/* Make the table for a fast CRC. */
static public int[] make_table()
{
int[] table = new int[256];
int c;
int n, k;
for (n = 0; n < 256; n++) {
c = n;
for (k = 0; k < 8; k++) {
if ((c & 1) != 0)
c = polyval ^ (c >>> 1);
else
c = c >>> 1;
}
table[n] = (int) c;
}
return table;
}
public int iterate(int state, int i)
{
return this.table[(state ^ i) & 0xff] ^ (state >>> 8);
}
#Override public int hash(int n) {
int h = -1;
h = iterate(h, n >>> 24);
h = iterate(h, n >>> 16);
h = iterate(h, n >>> 8);
h = iterate(h, n);
return h ^ -1;
}
#Override public String toString() { return getClass().getSimpleName(); }
}
static class TrigHasher implements Hasher
{
#Override public String toString() { return getClass().getSimpleName(); }
#Override public int hash(int n) {
double s = Math.sin(n);
return (int) Math.floor((1<<31)*s);
}
}
private static void test(Hasher hasher) {
System.out.println(hasher+":");
for (int i = 0; i < 64; ++i)
{
int h = hasher.hash(i);
System.out.println(String.format("%08x -> %08x %%2 = %d",
i,h,(h&1)));
}
for (int i = 0; i < 256; ++i)
{
System.out.print(hasher.hash(i) & 1);
}
System.out.println();
analyzeBits(hasher);
}
private static void analyzeBits(Hasher hasher) {
final int N = 65536;
final int maxrunlength=32;
int[][] runs = {new int[maxrunlength], new int[maxrunlength]};
int[] count = new int[2];
int prev = -1;
System.out.println("Run length test of "+N+" bits");
for (int i = 0; i < maxrunlength; ++i)
{
runs[0][i] = 0;
runs[1][i] = 0;
}
int runlength_minus1 = 0;
for (int i = 0; i < N; ++i)
{
int b = hasher.hash(i) & 0x1;
count[b]++;
if (b == prev)
++runlength_minus1;
else if (i > 0)
{
++runs[prev][runlength_minus1];
runlength_minus1 = 0;
}
prev = b;
}
++runs[prev][runlength_minus1];
System.out.println(String.format("%d zeros, %d ones", count[0], count[1]));
for (int i = 0; i < maxrunlength; ++i)
{
System.out.println(String.format("%d runs of %d zeros, %d runs of %d ones", runs[0][i], i+1, runs[1][i], i+1));
}
}
public static void main(String[] args) {
Hasher[] hashers = {
new MultiplicativeHasher1(),
GF32Hasher.CRC32,
new QuickHasher(),
new CRC32TableHasher(),
new TrigHasher()
};
for (Hasher hasher : hashers)
{
test(hasher);
}
}
}
The simplest hash for int value is the int value.
See Java Integer class
public int hashCode()
public static int hashCode(int value)
Returns:
a hash code value for this object, equal to the primitive int value represented by this Integer object.

simplifying fractions in Java

My task is to develop a rational class. If 500 and 1000 are my inputs, then (½) must be my output.
I have written a program on my own to find it.
Is there another best way to find the solution, or my program is already the best one?
public class Rational {
public static void main(String[] args){
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
int temp1 = n1;
int temp2 = n2;
while (n1 != n2){
if(n1 > n2)
n1 = n1 - n2;
else
n2 = n2 - n1;
}
int n3 = temp1 / n1 ;
int n4 = temp2 / n1 ;
System.out.print("\n Output :\n");
System.out.print(n3 + "/" + n4 + "\n\n" );
System.exit(0);
}
}
Interesting question. Here's some executable code that does it with minimal code:
/** #return the greatest common denominator */
public static long gcd(long a, long b) {
return b == 0 ? a : gcd(b, a % b);
}
public static String asFraction(long a, long b) {
long gcd = gcd(a, b);
return (a / gcd) + "/" + (b / gcd);
}
// Some tests
public static void main(String[] args) {
System.out.println(asFraction(500, 1000)); // "1/2"
System.out.println(asFraction(17, 3)); // "17/3"
System.out.println(asFraction(462, 1071)); // "22/51"
}
Bonus methods:
/** #return the lowest common multiple */
public static long lcm(long a, long b) {
return a * b / gcd(a, b);
}
/** #return the greatest common denominator */
public static long gcd(List<? extends Number> numbers) {
return numbers.stream().map(Number::longValue).reduce((a, b) -> gcd(a, b)).orElseThrow(NoSuchElementException::new);
}
/** #return the lowest common multiple */
public static long lcm(List<? extends Number> numbers) {
return numbers.stream().map(Number::longValue).reduce((a, b) -> lcm(a, b)).orElseThrow(NoSuchElementException::new);
}
You need the GCD. Either use BigInteger like Nathan mentioned or if you can't, use your own.
public int GCD(int a, int b){
if (b==0) return a;
return GCD(b,a%b);
}
Then you can divide each number by the GCD, like you have done above.
This will give you an improper fraction. If you need a mixed fraction then you can get the new numbers. Example if you had 1500 and 500 for inputs you would end up with 3/2 as your answer. Maybe you want 1 1/2. So you just divide 3/2 and get 1 and then get the remainder of 3/2 which is also 1. The denominator will stay the same.
whole = x/y;
numerator x%y;
denominator = y;
In case you don't believe me that this works, you can check out
http://en.wikipedia.org/wiki/Euclidean_algorithm
I just happen to like the recursive function because it's clean and simple.
Your algorithm is close, but not exactly correct. Also, you should probably create a new function if you want to find the gcd. Just makes it a little cleaner and easier to read. You can also test that function as well.
For reference, what you implemented is the original subtractive Euclidean Algorithm to calculate the greatest common divisor of two numbers.
A lot faster version is using the remainder from integer division, e.g. % instead of - in your loop:
while (n1 != 0 && n2 != 0){
if(n1 > n2)
n1 = n1 % n2;
else
n2 = n2 % n1;
}
... and then make sure you will use the one which is not zero.
A more streamlined version would be this:
while(n1 != 0) {
int old_n1 = n1;
n1 = n2 % n1;
n2 = old_n1;
}
and then use n1. Matt's answer shows a recursive version of the same algorithm.
You should make this class something other than a container for static methods. Here is a skeleton
import java.math.BigInteger;
public class BigRational
{
private BigInteger num;
private BigInteger denom;
public BigRational(BigInteger _num, BigInteger _denom)
{
//put the negative on top
// reduce BigRational using the BigInteger gcd method
}
public BigRational()
{
this(BigInteger.ZERO, BigInteger.ONE);
}
public BigRational add(BigRational that)
{
// return this + that;
}
.
.
.
//etc
}
}
I have a similar BigRational class I use. The GcdFunction is makes use of BigInteger's gcd function:
public class GcdFunction implements BinaryFunction {
#Override
public BigRational apply(final BigRational left, final BigRational right) {
if (!(left.isInteger() && right.isInteger())) {
throw new EvaluationException("GCD can only be applied to integers");
}
return new BigRational(left.getNumerator().gcd((right.getNumerator())));
}
}
BigRational contains a BigInteger numerator and denominator. isInteger() returns true if the simplified ratio's denominator is equal to 1.
Noticed that all answers here do not mention the iterative implementation of the Euclidean algorithm.
public static long gcdLongIterative(long a, long b) {
long tmp;
while (0 != b) {
tmp = b;
b = a % b;
a = tmp;
}
return a;
}
I implemented the validation test like #Bohemian and both recursive and iterative implementations work the same, however the iterative approach is faster. The benchmarks show small improvement, but it's improvement and overall it feels better to not use the stack so much and depend fully on the Java VM to optimize its implementation depend. Even if the benchmarks would be the same I would still feel better with the iterative as that would be more portable while the recursive was only optimized by my host Java, but might not be so well optimized on other's VMs.
Benchmark results (code is on the bottom of the answer):
(100 000 000 iterations)
gcd recursive: 3113ms
gcd iterative: 3079ms
gcd BigInteger: 13672ms
Signs:
One difference I noticed (besides the performance) is that the signs are handled differently, hand implemented Euclidean algorithm gcdLong and my gcdLongIterative behave the same, but both are different from BigInteger which tends to 'keep' the signs as they are. It seems that in essence the gcd and gcdLongIterative can return a negative number, while BigInteger will return positive only.
gcdLong and gcdLongIterative implementations:
-4/-2 => 2/1
-10/200 => 1/-20
10/-200 => 1/-20
BigInteger implementation tends to 'keep' the signs:
-4/-2 => -2/-1
-10/200 => -1/20
10/-200 => 1/-20
All results when used for fractions are valid, but it's worth considering post-process normalization if you expect the numbers in a specific 'style'.
For example, if the BigInteger behavior is preferred, then just returning absolute value should be enough, like here:
public static long gcdLongIterative(long a, long b) {
long tmp;
while (0 != b) {
tmp = b;
b = a % b;
a = tmp;
}
return Math.abs(a);
}
Performance:
Inspired by #Xabster benchmark (from Java: Get Greatest Common Divisor, which method is better?) I extended it to test all 3 implementations, in some cases both recursive and iterative were performing the same, however the iterative is slightly faster in most of the cases.
The benchmark code:
import java.math.BigInteger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
public class Test {
private static final int BENCHMARK_ITERATIONS = 100000000;
public static long gcdLong(long a, long b) {
return b == 0 ? a : gcdLong(b, a % b);
}
public static long gcdLongIterative(long a, long b) {
long tmp;
while (0 != b) {
tmp = b;
b = a % b;
a = tmp;
}
return a;
}
public static long gcdLongBigInteger(long a, long b) {
return BigInteger.valueOf(a).gcd(BigInteger.valueOf((b))).longValue();
}
public static String asFractionGcdLong(long a, long b) {
long gcd = gcdLong(a, b);
return (a / gcd) + "/" + (b / gcd);
}
public static String asFractionGcdLongIterative(long a, long b) {
long gcd = gcdLongIterative(a, b);
return (a / gcd) + "/" + (b / gcd);
}
public static String asFractionGcdLongBI(long a, long b) {
long gcd = gcdLongBigInteger(a, b);
return (a / gcd) + "/" + (b / gcd);
}
public static void test(String actual, String expected) {
boolean match = expected.equals(actual);
if (match) {
System.out.println("Actual and expected match=" + expected);
} else {
System.out.println("NO match expected=" + expected + " actual=" + actual);
}
}
public static class Values {
public long a;
public long b;
public String expected;
public Values(long a, long b, String expected) {
this.a = a;
this.b = b;
this.expected = expected;
}
}
public static void validityTest() {
List<Values> vals = new LinkedList<Values>(Arrays.asList(
new Values(500, 1000, "1/2"),
new Values(17, 3, "17/3"),
new Values(462, 1071, "22/51"),
new Values(-4, -2, "2/1"),
new Values(-10, 200, "1/-20"),
new Values(10, -200, "1/-20")
));
System.out.println("------ Recursive implementation -------");
vals.forEach(v -> test(asFractionGcdLong(v.a, v.b), v.expected));
System.out.println();
System.out.println("------ Iterative implementation -------");
vals.forEach(v -> test(asFractionGcdLongIterative(v.a, v.b), v.expected));
System.out.println();
System.out.println("------ BigInteger implementation -------");
vals.forEach(v -> test(asFractionGcdLongBI(v.a, v.b), v.expected));
System.out.println();
}
public static void benchMark() {
Random r = new Random();
long[] nums = new long[BENCHMARK_ITERATIONS];
for (int i = 0 ; i < nums.length ; i++) nums[i] = r.nextLong();
System.out.println("Waming up for benchmark...");
for (int i = 0 ; i < nums.length-1; i++) gcdLong(i, i + 1);
for (int i = 0 ; i < nums.length-1; i++) gcdLongIterative(i, i + 1);
for (int i = 0 ; i < nums.length-1; i++) gcdLongBigInteger(i, i + 1);
System.out.println("Started benchmark...");
long s = System.currentTimeMillis();
for (int i = 0 ; i < nums.length-1; i++) gcdLong(i, i + 1);
System.out.println("recursive: " + (System.currentTimeMillis() - s) + "ms");
s = System.currentTimeMillis();
for (int i = 0 ; i < nums.length-1; i++) gcdLongIterative(i, i + 1);
System.out.println("iterative: " + (System.currentTimeMillis() - s) + "ms");
s = System.currentTimeMillis();
for (int i = 0 ; i < nums.length-1; i++) gcdLongBigInteger(i, i + 1);
System.out.println("BigInteger: " + (System.currentTimeMillis() - s) + "ms");
}
public static void main(String[] args) {
validityTest();
benchMark();
}
}

Categories

Resources