Code to find quadratic roots fail when huge numbers are used - java

I got this problem from an online course and here I had to write a small program to find quadratic roots, and the return type should be Set<Integer>. I am still learning Java and still not familiar working with those types.
I think everything is not wrong until this part,
if(discriminant > 0) {
root1 = (int)(-b + Math.sqrt(discriminant)) / (2 * a);
root2 = (int)(-b - Math.sqrt(discriminant)) / (2 * a);
result.add(root1);
result.add(root2);
}
As I have to return the final roots as a Set<Integer> type I had to force convert double to int returned by 'Math.sqrt'. I am not sure if this is what causing the issues. And if so I am not sure if how to solve this, because I can't add double values to a set<Integer>.
I tested this code with few test cases, and it failed when using really big values, like ~2,000,000,000 for c.
And this is the code I came up with so far.
public class Quadratic {
public static Set<Integer> roots(int a, int b, int c) {
int root1;
int root2;
int discriminant = b * b - 4 * a * c;
Set<Integer> result = new HashSet<Integer>();
if(discriminant < 0) {
String rootsAreImaginary = "Roots are imaginary";
System.out.println(rootsAreImaginary);
}
if(discriminant == 0) {
root1 = (-b) / (2 * a);
root2 = root1;
result.add(root1);
result.add(root2);
}
if(discriminant > 0) {
root1 = (int)(-b + Math.sqrt(discriminant)) / (2 * a);
root2 = (int)(-b - Math.sqrt(discriminant)) / (2 * a);
result.add(root1);
result.add(root2);
}
return result;
}
If there are better ways to do this, please feel free to show me. Thank you so much in advance.

You can use BigDecimal or BigInteger to do the computations. These would have to be stored in a Set of the proper type, e.g. Set<BigDecimal>.
Both of those classes have methods to return the value of the related primitive (BigDecimal#doubleValue() and BigInteger#longValue()). But precision and size concerns still apply as you may not be able to fit the result into the class's related primitive.

Related

Karatsuba multiplication java recursion code not working?

I am trying to multiply two numbers using karatsuba multiplication. My java code is not working. I have used string as parameters and arguments so that we can multiply two n digit numbers (n is even). Also, I don't want to use long or BigInteger. Please help me to figure out my code mistake.
class karat{
public static String karatsuba(String first, String second){
if(first.length() <= 1 || second.length() <= 1)
return String.valueOf(Long.parseLong(first)*Long.parseLong(second));
String a = karatsuba(first.substring(0, first.length()/2), second.substring(0, second.length()/2));
String b = karatsuba(first.substring(first.length() - first.length()/2, first.length()), second.substring(second.length() - second.length()/2, second.length()));
String c = karatsuba(String.valueOf(Long.parseLong(first.substring(0, first.length()/2)) + Long.parseLong(first.substring(first.length() - first.length()/2, first.length()))), String.valueOf(Long.parseLong(second.substring(0, second.length()/2)) + Long.parseLong(second.substring(second.length() - second.length()/2, second.length()))));
String d = String.valueOf(Long.parseLong(c) - Long.parseLong(b) - Long.parseLong(a));
return String.valueOf(((int)Math.pow(10, first.length()))*(Long.parseLong(a)) + (((int)Math.pow(10, first.length()/2))*Long.parseLong(d)) + (Long.parseLong(c)));
}
public static void main(String[] args){
String result = karatsuba("1234", "5678");
System.out.println(result); }
}
Can you also please refine my code.
Numbers passed for multiplication - 1234 and 5678
Output is - 6655870 (Incorrect)
Output should be - 7006652 (Correct)
Thank you
First of all I tried look at your code, it gets a programmer to get lost, few things before we go into solution.
General advice. It is not good practice to convert string to value and back and forward like you do, it does not work like this. I tried as well to debug your code, it is just devil circle.
So I would start with check if value length and the maximum one.
Than if one of the values is less than 2 of length mean every thing less than 10 do multiplication otherwise do karatsuba recursion algorithm.
Here is the solution:
public static long karatsuba(long num1, long num2) {
int m = Math.max(
String.valueOf(num1).length(),
String.valueOf(num2).length()
);
if (m < 2)
return num1 * num2;
m = (m / 2) + (m % 2);
long b = num1 >> m;
long a = num1 - (b << m);
long d = num2 >> m;
long c = num2 - (d << m);
long ac = karatsuba(a, c);
long bd = karatsuba(b, d);
long abcd = karatsuba(a + b, c + d);
return ac + (abcd - ac - bd << m) + (bd << 2 * m);
}
Some test;
public static void main(String[] args) {
System.out.println(karatsuba(1, 9));
System.out.println(karatsuba(1234, 5678));
System.out.println(karatsuba(12345, 6789));
}
The output would be
9
7006652
83810205
It is less pain than your Stringish code. Btw, the solution is inspired from the pesudo in wiki and this class.
Interesting algorithm. One mistake is in
return String.valueOf(((int)Math.pow(10, first.length()))*(Long.parseLong(a)) + (((int)Math.pow(10, first.length()/2))*Long.parseLong(d)) + (Long.parseLong(c)));
At the end, it should be Long.parseLong(b) instead of Long.parseLong(c).
And in intermediate calculations, it can happen that the two strings are of different lengths. That also doesn't work correctly.
Please, allow some comments to improve the implementation. The idea to use strings seems to allow for big numbers, but then you introduce things like Long.parseLong() or (int)Math.pow(10, first.length()), limiting you to the long or int range.
If you really want to do big numbers, write your own String-based addition and power-of-ten multiplication (that one being trivial by appending some zeroes).
And, try to avoid names like a, b, c, or d - it's too easy to forget what they mean, as was your original mistake. E.g. the names from Wikipedia are a little bit better (using z0, z1 and z2), but still not perfect...

Numerical accuracy with log probability Java implementation

Sometimes when you do calculations with very small probabilities using common data types such as doubles, numerical inaccuracies cascade over multiple calculations and lead to incorrect results. Because of this it is recommended to use log probabilities, which improve numerical stability. I have implemented log probabilities in Java and my implementation works, but it has worse numerical stability than using raw doubles. What is wrong with my implementation? What is an accurate and efficient way to perform many consecutive calculations with small probabilities in Java?
I'm unable to provide a neatly contained demonstration of this problem because the inaccuracies cascade over many calculations. However, here is proof that a problem exists: this submission to a CodeForces contest fails due to numerical accuracy. Running test #7 and adding debug prints clearly show that from day 1774, numerical errors begin cascading until the sum of probabilities drops to 0 (when it should be 1). After replacing my Prob class with a simple wrapper over doubles the exact same solution passes tests.
My implementation of multiplying probabilities:
a * b = Math.log(a) + Math.log(b)
My implementation of addition:
a + b = Math.log(a) + Math.log(1 + Math.exp(Math.log(b) - Math.log(a)))
The stability problem is most likely contained within those 2 lines, but here is my entire implementation:
class Prob {
/** Math explained: https://en.wikipedia.org/wiki/Log_probability
* Quick start:
* - Instantiate probabilities, eg. Prob a = new Prob(0.75)
* - add(), multiply() return new objects, can perform on nulls & NaNs.
* - get() returns probability as a readable double */
/** Logarithmized probability. Note: 0% represented by logP NaN. */
private double logP;
/** Construct instance with real probability. */
public Prob(double real) {
if (real > 0) this.logP = Math.log(real);
else this.logP = Double.NaN;
}
/** Construct instance with already logarithmized value. */
static boolean dontLogAgain = true;
public Prob(double logP, boolean anyBooleanHereToChooseThisConstructor) {
this.logP = logP;
}
/** Returns real probability as a double. */
public double get() {
return Math.exp(logP);
}
#Override
public String toString() {
return ""+get();
}
/***************** STATIC METHODS BELOW ********************/
/** Note: returns NaN only when a && b are both NaN/null. */
public static Prob add(Prob a, Prob b) {
if (nullOrNaN(a) && nullOrNaN(b)) return new Prob(Double.NaN, dontLogAgain);
if (nullOrNaN(a)) return copy(b);
if (nullOrNaN(b)) return copy(a);
double x = a.logP;
double y = b.logP;
double sum = x + Math.log(1 + Math.exp(y - x));
return new Prob(sum, dontLogAgain);
}
/** Note: multiplying by null or NaN produces NaN (repping 0% real prob). */
public static Prob multiply(Prob a, Prob b) {
if (nullOrNaN(a) || nullOrNaN(b)) return new Prob(Double.NaN, dontLogAgain);
return new Prob(a.logP + b.logP, dontLogAgain);
}
/** Returns true if p is null or NaN. */
private static boolean nullOrNaN(Prob p) {
return (p == null || Double.isNaN(p.logP));
}
/** Returns a new instance with the same value as original. */
private static Prob copy(Prob original) {
return new Prob(original.logP, dontLogAgain);
}
}
Problem was caused by the way Math.exp(z) was used in this line:
a + b = Math.log(a) + Math.log(1 + Math.exp(Math.log(b) - Math.log(a)))
When z reaches extreme values, numerical accuracy of double is not enough for the output of Math.exp(z). This causes us to lose information, produce an inaccurate result, and then these results cascade over multiple calculations.
When z >= 710 then Math.exp(z) = Infinity
When z <= -746 then Math.exp(z) = 0
In the original code I was calling Math.exp with y - x and arbitrarily choosing which is x and which is why. Let's instead choose y and x based on which is larger, so that z is negative rather than positive. The point where we get overflow is further on the negative side (746 rather than 710) and more importantly, when we overflow, we end up at 0 rather than infinity. Which is what we want with a low probability.
double x = Math.max(a.logP, b.logP);
double y = Math.min(a.logP, b.logP);
double sum = x + Math.log(1 + Math.exp(y - x));

How to reverse engineer hash function

I am trying to create a function that generates a hash key based upon where in the hash table I want the value to go.
My hash function is (a + b * (key) ) % c = hash value. I've seen a similar question to this on SO, and what I tried is replacing b * (key) with d and just doing:
private int ReverseModulus(int a, int b, int c, int hashValue)
{
if(hashValue >= c)
return -1;
if(a < hashValue)
return (hashValue - a) / b;
return (c + hashValue - a) / b;
}
but it seems that most of the time hashValue != Hash(ReverseModulus(a,b,c, hashValue)).
I was wondering if the approach is wrong or if there is just an error in the code.
You're using the wrong kind of division. You're doing integer division, but you need to be doing modular division. In Java you can use BigInteger:
bh = new BigInteger(hashValue);
ba = new BigInteger(a);
bc = new BigInteger(c);
bn = bh.subtract(ba);
return bn.modInverse(bc).intValue();
and C# presumably has similar library functions.

Read an ecuation from a .txt file and set it as return for a method

I am trying to solve an given equation using Newton Tangent Method. The Tangent Method works by assuming the solution is somewhere in the a-b interval where a and b are given and that the function is continuous on the [a,b] interval.
I already wrote the program and it's working fine but now I have to make a GUI for it and the equation must be read from a text file.
My issues is that I do not know how to get the equation from the .txt file and set it as return for my function method. This should work for any given equation.
Below is my code for the equation: x^3 -4 * x^2 + 5 * x^1 -12
Here is the code:
static double f(double x) { // the function from the .txt file
//return Math.pow(x, 3) - 4* Math.pow(x,2) + 5 * Math.pow(x, 1) - 12;
return x * x * x - 4 * x * x + 5 * x - 12;
}
static double df(double x) { // the function derivative
return 3 * x * x - 8 * x + 5;
}
static String metTangent() {
double b = 4, c, reduceIntervalBy, precision = 0.00000000001;
// reduceIntervalBy holds the value of how much should the interval be reduced by, starting from b to a, so from right to left
DecimalFormat decimalformat = new DecimalFormat("#.00000000000000");
do {
c = b - f(b) / df(b);
//System.out.println(c);
reduceIntervalBy = b - c;
b = c;
} while (reduceIntervalBy > precision );
return "The solution is: " + decimalformat .format(c);
}
Solved it. Thanks everyone for help :)
you can use the below method to read the equation from a text file.
static String getEquation () throws Exception
{
Scanner in = new Scanner(new FileReader("C:\\test1.txt"));
StringBuffer br = new StringBuffer();
while(in.hasNext())
{
br.append(in.next());
}
return br.toString();
}
Then to parse the equation and value to be evaluated to the below function.
static Object f(double x,String eq) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
engine.put("x",x);
return engine.eval(eq);
}
To avoid having to write a parser, one can leverage an implementation of the Java Expression Language, e.g. https://uel.java.net/get-started.html. Alternatively, the Java Scripting API can do the same thing. Both is a little overkill for the small task but should quickly get you started.
Edit: See #robin's answer for an example using the scripting API.
I suspect this task is MUCH harder than you imagine, these are the basic steps you need to look at implementing:
Read the equation from a text file as a string
Write a parser to make some sort of structure of java objects from this string that represent a path to evaluate the equation for a given value. (this is the hard part - try looking for sources on 'descent parser' and 'shunting yard algorithm .
once you have this structure that can evaluate the equation for any x then the newton's method is easily implemented just as you do.
Good Luck

My code is working, but I'm trying to understand something regarding constructors.

I've created an new class that can create rational numbers and can calculate with rational numbers. My code is working fine, I was trying a lot of things and it works, however I don't really understand what is happening in my constructors. I've looked into the java tutorial on Oracle, but didn't find my answer.
My questions is about my temporary argument in my constructor, (Rational B2)
public Rational count(Rational b2) { //ok
int newNumerator = (this.Numerator * b2.denominator) + (this.denominator * b2.Numerator);
int newDenominator = this.denominator * b2.denominator;
Rational r = new Rational(newNumerator, newDenominator);
return r;
My questions is: What is happing with b2? What is the function of b2 and where is it stored?
Hopefully someone can explain it to me so I have a better understanding about my code :)
Your method is not a constructor. b2 is just used to get its denominator and numerator in order to create a new Rational instance.
The method could have been:
public Rational count(int otherNumerator, int otherDenominator) { //ok
int newNumerator = (this.Numerator * otherDenominator)
+ (this.denominator * otherNumerator);
int newDenominator = this.denominator * otherDenominator;
Rational r = new Rational(newNumerator, newDenominator);
return r;
}

Categories