I'm having trouble with desiging a method to express an integer n as an integer pair (base, exponent) such that n == base ^ exponent, for an assignment. Below is the contract for the method. #pre specifies what n has to be, #post defines what the output has to be.
/**
* Writes a number as a power with maximal exponent.
*
* #param n the number to 'powerize'
* #return power decomposition of {#code n} with maximal exponent
* #throws IllegalArgumentException if precondition violated
* #pre {#code 2 <= n}
* #post {#code n == power(\result) &&
* (\forall int b, int e;
* 2 <= b && 1 <= e && n == b ^ e;
* e <= \result.exponent)}
*/
public static Power powerize(int n){}
Where the class Power is just a Pair instance.
I already managed to solve this problem using a naive approach, in which I compute the value of the base and exponent by computing log(n) / log(b) with 2 <= b <= sqrt(n). But the assignment description says I have to produce an ellegant & efficient method and I couldn't find a way to compute this more efficiently.
After consulting some books I designed the following solution:
Input int n:
Let p1...pm be m unique primes.
Then we can express n as:
n = p1e1 x ... x pmem.
Then compute the gcd d of e1 ... em using the euclidean algorithm.
Then we express n as:
n = (p1e1/d x ... x pmem/d)d.
now we have:
b = p1e1/d x ... x pmem/d
e = d
return new Power(b, e)
Related
I'm trying to make a method that factorizes the number n into the product of primes. For example factorizing 12 would result in 3 x 2^2. The first block of code factorizes n into loose numbers so 12 = 3 x 2 x 2 and places them in f. The second block is then supposed to store these numbers in p as powers instead of loose numbers by counting the exponent as the amount of times a number occurs in f, so 3^1 x 2^2 instead of 3 x 2 x 2. This is done with an object Power which stores the base and exponent of a number.
For some reason however, this code keeps returning empty arrays. And after looking it over many times I still have no idea why this would be the case. Is there something I'm doing wrong or that I misunderstand?
/**
* factorize n
*
* #param n the number to 'powerize'
* #modifies none
* #pre {#code 2 <= n}
* #return factorization of n
*/
public static List<Power> factorize(int n) {
List<Integer> f = new ArrayList<Integer>(); // f are factors
for (int i = 2; i <= n; i++) {
while (n % i == 0) {
f.add(i);
n /= i;
}
}
List<Power> p = new ArrayList<Power>(); // p are the factors with powers
for (int j = 2; j <= n; j++) { //j will be the base
int e = 0; //exponent
for (int k = 0; k <= f.size(); k++) {
if (f.get(k) == j) {
e++;
}
}
p.add(new Power(j, e));
}
return p; //returns factors in powered form
}
I'll add the code for the Power object in case it's necessary.
/**
* Record containing a base and an exponent.
*
* #inv {#code 0 <= base && 0 <= exponent}
*/
public static class Power { // BEGIN RECORD TYPE
/**
* The base.
*/
public int base;
/**
* The exponent.
*/
public int exponent;
/**
* Constructs a Power with given base and exponent.
*
* #param base the base
* #param exponent the exponent
* #pre {#code 0 <= base && 0 <= exponent}
* #post {#code \result.base == base && \result.exponent == exponent}
*/
public Power(int base, int exponent) {
this.base = base;
this.exponent = exponent;
}
} // END RECORD TYPE
if you debug you will see that your n variable value is 1 after first for cycle. That's why second cycle not started at all
I am currently doing MIT's OCW 6.005 Elements of Software Construction for self- study.
I am on problem set 1.
The part I am currently stuck on is 1.d. It asks me to "Implement computePiInHex() in PiGenerator. Note that this function should
only return the fractional digits of Pi, and not the leading 3."
Here is what I have so far:
public class PiGenerator {
/**
* Returns precision hexadecimal digits of the fractional part of pi.
* Returns digits in most significant to least significant order.
*
* If precision < 0, return null.
*
* #param precision The number of digits after the decimal place to
* retrieve.
* #return precision digits of pi in hexadecimal.
*/
public static int[] computePiInHex(int precision) {
if(precision < 0) {
return null;
}
return new int[0];
}
/**
* Computes a^b mod m
*
* If a < 0, b < 0, or m < 0, return -1.
*
* #param a
* #param b
* #param m
* #return a^b mod m
*/
public static int powerMod(int a, int b, int m) {
if(a < 0 || b < 0 || m < 0)
return -1;
return (int) (Math.pow(a, b)) % m;
}
/**
* Computes the nth digit of Pi in base-16.
*
* If n < 0, return -1.
*
* #param n The digit of Pi to retrieve in base-16.
* #return The nth digit of Pi in base-16.
*/
public static int piDigit(int n) {
if (n < 0) return -1;
n -= 1;
double x = 4 * piTerm(1, n) - 2 * piTerm(4, n) -
piTerm(5, n) - piTerm(6, n);
x = x - Math.floor(x);
return (int)(x * 16);
}
private static double piTerm(int j, int n) {
// Calculate the left sum
double s = 0;
for (int k = 0; k <= n; ++k) {
int r = 8 * k + j;
s += powerMod(16, n-k, r) / (double) r;
s = s - Math.floor(s);
}
// Calculate the right sum
double t = 0;
int k = n+1;
// Keep iterating until t converges (stops changing)
while (true) {
int r = 8 * k + j;
double newt = t + Math.pow(16, n-k) / r;
if (t == newt) {
break;
} else {
t = newt;
}
++k;
}
return s+t;
}
}
The main method initiates a constant and then calls computePiInHex().
public static final int PI_PRECISION = 10000;
int [] piHexDigits = PiGenerator.computePiInHex(PI_PRECISION);
From my knowledge, the method piDigits() gets the nth digit of pi in base 16. So in computePiHex, should implement the BBP digit-extraction algorithm for Pi? Otherwise could someone point me in the right direction because I don't know what they're asking for in computePiInHex().
Try a different powermod algorithm.
For me this article helped a lot:
http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-005-elements-of-software-construction-fall-2011/assignments/MIT6_005F11_ps1.pdf
The actual algorithm I used is based on the pseudocode from Applied Cryptography by Bruce Schneier
https://en.m.wikipedia.org/wiki/Modular_exponentiation
function modular_pow(base, exponent, modulus)
if modulus = 1 then return 0
Assert :: (modulus - 1) * (modulus - 1) does not overflow base
result := 1
base := base mod modulus
while exponent > 0
if (exponent mod 2 == 1):
result := (result * base) mod modulus
exponent := exponent >> 1
base := (base * base) mod modulus
return result
I found a formula in the Internet for calculating the trapezoid method , it works as it should, but I do not see why should I performed the following lines in the trapez method:
sum = 0.5 * bef + (h * sum);
i= i+ 2
The first iteration performed by the following command in main :
tra[0] = 0.5 * ((b - a) / n) * (function(a) + function(b));
//calculates the first step value
the trapez method for the next iterations:
/**
* calculate the next step with trapez method
* #param a -lower limit
* #param b -upper limit
* #param bef -previous step value
* #param n -number of dividing points
* #return integral area
*/
public static double trapz(double a, double b,double bef, int n)
{
double sum = 0;
double h = ((b - a)/n);
for (int i = 1; i <= n; i = i + 2) {
sum += function(a + (i) * h);
}
sum = 0.5 * bef + (h * sum);
return sum;
}
The function would be used in conjunction with a driver loop that doubles the number of subintervals at each iteration, refining the estimated integral until the difference from one iteration to the next is less than some threshold criterion. It is desirable in such an endeavor to avoid repeating computations that have already been performed, and that's the point of the lines you asked about.
Consider the function values that are needed when applying the trapezoid rule on a given number of subintervals. Now consider the function values needed for splitting each subinterval in half and applying the trapezoid rule to those subintervals. Half (give or take 1) of the function values needed in the latter case are the same ones needed in the former. The code presented simply reuses the previously computed values (0.5 * bef), adding to them only the new values (i = i + 2). It must scale down the previous estimate by a factor of two to account for splitting the subintervals in two.
Note that for the code to be right, it appears that argument n must represent the number of subintervals of the integration region, not the number of dividing points as its documentation claims.
I have a BigInteger number, for example beyond 264.
Now i want to calculate the logarithm of that BigInteger number, but the method BigInteger.log() does not exist. How do I calculate the (natural) logarithm of my large BigInteger value?
If you want to support arbitrarily big integers, it's not safe to just do
Math.log(bigInteger.doubleValue());
because this would fail if the argument exceeds the double range (about 2^1024 or 10^308, i.e. more than 300 decimal digits ).
Here's my own class that provides the methods
double logBigInteger(BigInteger val);
double logBigDecimal(BigDecimal val);
BigDecimal expBig(double exponent);
BigDecimal powBig(double a, double b);
They work safely even when the BigDecimal/BigInteger are too big (or too small) to be representable as a double type.
import java.math.*;
/**
* Provides some mathematical operations on {#code BigDecimal} and {#code BigInteger}.
* Static methods.
*/
public class BigMath {
public static final double LOG_2 = Math.log(2.0);
public static final double LOG_10 = Math.log(10.0);
// numbers greater than 10^MAX_DIGITS_10 or e^MAX_DIGITS_E are considered unsafe ('too big') for floating point operations
private static final int MAX_DIGITS_10 = 294;
private static final int MAX_DIGITS_2 = 977; // ~ MAX_DIGITS_10 * LN(10)/LN(2)
private static final int MAX_DIGITS_E = 677; // ~ MAX_DIGITS_10 * LN(10)
/**
* Computes the natural logarithm of a {#link BigInteger}
* <p>
* Works for really big integers (practically unlimited), even when the argument
* falls outside the {#code double} range
* <p>
*
*
* #param val Argument
* #return Natural logarithm, as in {#link java.lang.Math#log(double)}<br>
* {#code Nan} if argument is negative, {#code NEGATIVE_INFINITY} if zero.
*/
public static double logBigInteger(BigInteger val) {
if (val.signum() < 1)
return val.signum() < 0 ? Double.NaN : Double.NEGATIVE_INFINITY;
int blex = val.bitLength() - MAX_DIGITS_2; // any value in 60..1023 works here
if (blex > 0)
val = val.shiftRight(blex);
double res = Math.log(val.doubleValue());
return blex > 0 ? res + blex * LOG_2 : res;
}
/**
* Computes the natural logarithm of a {#link BigDecimal}
* <p>
* Works for really big (or really small) arguments, even outside the double range.
*
* #param val Argument
* #return Natural logarithm, as in {#link java.lang.Math#log(double)}<br>
* {#code Nan} if argument is negative, {#code NEGATIVE_INFINITY} if zero.
*/
public static double logBigDecimal(BigDecimal val) {
if (val.signum() < 1)
return val.signum() < 0 ? Double.NaN : Double.NEGATIVE_INFINITY;
int digits = val.precision() - val.scale();
if (digits < MAX_DIGITS_10 && digits > -MAX_DIGITS_10)
return Math.log(val.doubleValue());
else
return logBigInteger(val.unscaledValue()) - val.scale() * LOG_10;
}
/**
* Computes the exponential function, returning a {#link BigDecimal} (precision ~ 16).
* <p>
* Works for very big and very small exponents, even when the result
* falls outside the double range.
*
* #param exponent Any finite value (infinite or {#code Nan} throws {#code IllegalArgumentException})
* #return The value of {#code e} (base of the natural logarithms) raised to the given exponent,
* as in {#link java.lang.Math#exp(double)}
*/
public static BigDecimal expBig(double exponent) {
if (!Double.isFinite(exponent))
throw new IllegalArgumentException("Infinite not accepted: " + exponent);
// e^b = e^(b2+c) = e^b2 2^t with e^c = 2^t
double bc = MAX_DIGITS_E;
if (exponent < bc && exponent > -bc)
return new BigDecimal(Math.exp(exponent), MathContext.DECIMAL64);
boolean neg = false;
if (exponent < 0) {
neg = true;
exponent = -exponent;
}
double b2 = bc;
double c = exponent - bc;
int t = (int) Math.ceil(c / LOG_10);
c = t * LOG_10;
b2 = exponent - c;
if (neg) {
b2 = -b2;
t = -t;
}
return new BigDecimal(Math.exp(b2), MathContext.DECIMAL64).movePointRight(t);
}
/**
* Same as {#link java.lang.Math#pow(double,double)} but returns a {#link BigDecimal} (precision ~ 16).
* <p>
* Works even for outputs that fall outside the {#code double} range.
* <br>
* The only limitation is that {#code b * log(a)} cannot exceed the {#code double} range.
*
* #param a Base. Should be non-negative
* #param b Exponent. Should be finite (and non-negative if base is zero)
* #return Returns the value of the first argument raised to the power of the second argument.
*/
public static BigDecimal powBig(double a, double b) {
if (!(Double.isFinite(a) && Double.isFinite(b)))
throw new IllegalArgumentException(
Double.isFinite(b) ? "base not finite: a=" + a : "exponent not finite: b=" + b);
if (b == 0)
return BigDecimal.ONE;
else if (b == 1)
return BigDecimal.valueOf(a);
if (a <= 0) {
if (a == 0) {
if (b >= 0)
return BigDecimal.ZERO;
else
throw new IllegalArgumentException("0**negative = infinite b=" + b);
} else
throw new IllegalArgumentException("negative base a=" + a);
}
double x = b * Math.log(a);
if (Math.abs(x) < MAX_DIGITS_E)
return BigDecimal.valueOf(Math.pow(a, b));
else
return expBig(x);
}
}
I had some help from google but apparently you don't need to apply log to your very big BigInteger numbers directly, since it can be broken down in the following way:
928 = 1000 * 0.928
lg 928 = lg 1000 + lg 0.928 = 3 + lg 0.928
Your problem is therefore reduced to the computation/approximation of logarithms that allow for arbitrary increasing precision, maybe math.stackexchange.com?
Convert it into a BigDecimal liek this:
new BigDecimal(val); // where val is a BigInteger
and call log from BigDecimalUtils on it :D
How accurate do you need it to be? If you only need 15 digits of accuracy you can do
BigInteger bi =
double log = Math.log(bi.doubleValue());
This would work for values up to 1023 bits. After that the value would not fit into a double anymore.
If you can use Google Guava, and only require base 2 or base 10 log, you can use methods from Guava's BigIntegerMath class.
If you need a different base, you can always use the logarithm change-of-base formula to convert from one of these, to the one you need.
I'm trying to write a function in Java that calculates the n-th root of a number. I'm using Newton's method for this. However, the user should be able to specify how many digits of precision they want. This is the part with which I'm having trouble, as my answer is often not entirely correct. The relevant code is here: http://pastebin.com/d3rdpLW8. How could I fix this code so that it always gives the answer to at least p digits of precision? (without doing more work than is necessary)
import java.util.Random;
public final class Compute {
private Compute() {
}
public static void main(String[] args) {
Random rand = new Random(1230);
for (int i = 0; i < 500000; i++) {
double k = rand.nextDouble()/100;
int n = (int)(rand.nextDouble() * 20) + 1;
int p = (int)(rand.nextDouble() * 10) + 1;
double math = n == 0 ? 1d : Math.pow(k, 1d / n);
double compute = Compute.root(n, k, p);
if(!String.format("%."+p+"f", math).equals(String.format("%."+p+"f", compute))) {
System.out.println(String.format("%."+p+"f", math));
System.out.println(String.format("%."+p+"f", compute));
System.out.println(math + " " + compute + " " + p);
}
}
}
/**
* Returns the n-th root of a positive double k, accurate to p decimal
* digits.
*
* #param n
* the degree of the root.
* #param k
* the number to be rooted.
* #param p
* the decimal digit precision.
* #return the n-th root of k
*/
public static double root(int n, double k, int p) {
double epsilon = pow(0.1, p+2);
double approx = estimate_root(n, k);
double approx_prev;
do {
approx_prev = approx;
// f(x) / f'(x) = (x^n - k) / (n * x^(n-1)) = (x - k/x^(n-1)) / n
approx -= (approx - k / pow(approx, n-1)) / n;
} while (abs(approx - approx_prev) > epsilon);
return approx;
}
private static double pow(double x, int y) {
if (y == 0)
return 1d;
if (y == 1)
return x;
double k = pow(x * x, y >> 1);
return (y & 1) == 0 ? k : k * x;
}
private static double abs(double x) {
return Double.longBitsToDouble((Double.doubleToLongBits(x) << 1) >>> 1);
}
private static double estimate_root(int n, double k) {
// Extract the exponent from k.
long exp = (Double.doubleToLongBits(k) & 0x7ff0000000000000L);
// Format the exponent properly.
int D = (int) ((exp >> 52) - 1023);
// Calculate and return 2^(D/n).
return Double.longBitsToDouble((D / n + 1023L) << 52);
}
}
Just iterate until the update is less than say, 0.0001, if you want a precision of 4 decimals.
That is, set your epsilon to Math.pow(10, -n) if you want n digits of precision.
Let's recall what the error analysis of Newton's method says. Basically, it gives us an error for the nth iteration as a function of the error of the n-1 th iteration.
So, how can we tell if the error is less than k? We can't, unless we know the error at e(0). And if we knew the error at e(0), we would just use that to find the correct answer.
What you can do is say "e(0) <= m". You can then find n such that e(n) <= k for your desired k. However, this requires knowing the maximal value of f'' in your radius, which is (in general) just as hard a problem as finding the x intercept.
What you're checking is if the error changes by less than k, which is a perfectly acceptable way to do it. But it's not checking if the error is less than k. As Axel and others have noted, there are many other root-approximation algorithms, some of which will yield easier error analysis, and if you really want this, you should use one of those.
You have a bug in your code. Your pow() method's last line should read
return (y & 1) == 1 ? k : k * x;
rather than
return (y & 1) == 0 ? k : k * x;