I saw this question of mapping numbers algorithm.
I am trying to implement the #PeterAllenWebb solution in java like this:
long A = 1l;
long B = 999999999l;
long C = 1000000000l;
long D = 9999999999l;
long X = 999999998l;
long Y = (D-C)*(X-A)/(B-A) + C;
System.out.println("original is " + X);
long reverseX = (B-A)*(Y-C)/(D-C) + A;
System.out.println("reverse is " + reverseX);
However, this doesn't always work.
See below:
X reverseX
999999998 999999997
1 1
999999999 999999999
12 11
As you can see, only minimum (A) and maximum (B) are returning fine.
For the rest, I need to add 1. This seems to me as floor/round/Math issue and I don't want to rely on the JVM that calculates it. I would like it to always work.
How can I make the above work for reverseX?
You are facing an age old issue. By default division is double in Java. So if your division result is 1.0 or 1.3 or 1.9 it will be truncated to 1. In your case the same is happening. Try changing it to double from long as below
double A = 1L;
double B = 999999999l;
double C = 1000000000l;
double D = 9999999999l;
double X = 999999998l;
double Y = (D - C) * (X - A) / (B - A) + C;
System.out.println("original is " + new DecimalFormat("#").format(X));
double reverseX = (B - A) * (Y - C) / (D - C) + A;
System.out.println("reverse is "
+ new DecimalFormat("#").format(reverseX));
Related
Only required in java, also without using strings or any specific objects, (just use maths)
problem is
double a = 13.564;
//now i want
int b = 13;
int c = 564;
Using String it would be easier as we don't need to know how many decimal there is
double a = 13.564;
String[] parts = Double.toString(a).split("\\.");
int b = Integer.parseInt(parts[0]);
int c = Integer.parseInt(parts[1]);
System.out.println(b + "/" + c);
With math only, you need to be careful so, a way is so multiply the number so there is no decimal part, the retrieve what was the decimal part
double a = 13.564;
int b = (int) a;
double power = Math.pow(10, BigDecimal.valueOf(a).scale());
int c = (int) (a * power - b * power);
System.out.println(b + "/" + c);
I've been trying a lot but it only shows NaN. I'm not sure if I'm doing the right thing.
class Imaginary{
double a = 2;
double b = 3;
double c = 5;
double result = b * b - 4 * a * c;
if(result < 0.0){
double im1 = -2 + (Math.sqrt((result))/ 10);
double im2 = -2 - (Math.sqrt((result))/ 10);
System.out.println("x = " + imaginary1 + " or x = " + imaginary2);
}
}
You need to take negate result to make it positive before taking the square root (taking square roots of negative numbers always results in NaN) and append "i" before printing.
double real = -b / (2*a);
double img = Math.sqrt(-result) / (2*a);
System.out.println("x = " + real + " + " + img +"i or x = " + real + " - " + img + "i");
You shouldn't use sqrt(result) since it will always result in you taking the square root of a negative number (that is your condition for result). Instead try to use a formula (eg completing the square).
Hope it answers your question :)
Since you have a complex root, you need to work with complex numbers to solve the equation. Java lacks builtin support for complex numbers, but you can e.g. use Apache Commons:
if (result < 0.0) {
final Complex cb = new Complex(-b, 0.0);
final Complex root = new Complex(result, 0.0).sqrt();
final Complex r1 = cb.add(root).divide(2 * a);
final Complex r2 = cb.subtract(root).divide(2 * a);
}
So I want to run Karatsuba Algorithm without using class BigInteger in Java, so upon following the pseudo-code and this question, I came with the following code
public static long recKaratsuba(long i1, long i2){
if(i1<10 || i2<10) {
return i1*i2 ;
}
long len = Math.round(Long.toString(Math.max(i1,i2)).length());
long N = Math.round(len/2) ;
long b = (long) (i1% Math.pow(10, N)) ;
long a = (long) (i1/ Math.pow(10,N));
long d = (long) (i2% Math.pow(10,N)) ;
long c = (long) (i2/ Math.pow(10,N));
//System.out.println("a,b,c,d :" + a + b + c + d);
long ac = recKaratsuba(a, c) ;
long bd = recKaratsuba(b, d) ;
long pos = recKaratsuba(a+b,c+d) ;
return ((long)(bd + ac*Math.pow(10,len) + (pos -ac -bd)*Math.pow(10,N) )) ;
}
Now, the problem with this is that it's producing the wrong answer, 1234*5678 is giving 11686652, which should've been 7006652.
As a beginner to Java and algorithms, I am unable to pinpoint the exact bug in this code, also I do realize that this program is very inefficient and doesn't work for more than 4 digits (according to the linked question ). But this is intuitively what I came up with originally after learning the pseudo-code.
So my question is, what is the problem in my code and how do I execute the following algorithm without using the BigInteger method?
There are a few things i notice:
Instead of i1 and i2 maybe use x and y
Variables len and N are int, not long
No need to round the maximum of the lengths of the string-representations: Lengths are ints, ints are whole numbers and cant be rounded
No need to round the division by 2: Dividing a whole number will always result in a whole number (integer division is done)
The error is in the return-statement: Math.pow(10, len) should be Math.pow(10, 2 * N) instead, this is important if N is uneven
Avoid multiple identical calculations: especially Math.pow(10, N)
The fixed code gives the correct results for all examples that i have tested.
public static long recKaratsuba2(long x, long y) {
if (x < 10 || y < 10) {
return x * y;
}
int len = Long.toString(Math.max(x, y)).length();
double den = Math.pow(10, len / 2);
long a = (long) (x / den);
long b = (long) (x % den);
long c = (long) (y / den);
long d = (long) (y % den);
long ac = recKaratsuba2(a, c);
long bd = recKaratsuba2(b, d);
long pos = recKaratsuba2(a + b, c + d);
return (long) (bd + den * (ac * den + (pos - ac - bd)));
}
I am using the pointwise mutual information (PMI) association measure to calculate how frequently words co-occure by using word-frequencies obtained from a large corpus.
I am calculating PMI via the classical formulae of
log(P(X,Y) / (P(X)*P(Y))
and using the contingency table notation with joint- and marginal frequencies I found on http://collocations.de/AM/index.html
The results I get are very similar, but not the same. As far as I understood things both methods should result in the exact same result value.
I made a little Java-programm (minimal working example) that uses word-frequencies from a corpus using both formulae. I get different results for the two methods. Does someone know why ?
public class MutualInformation
{
public static void main(String[] args)
{
long N = 1024908267229L;
// mutual information = log(P(X,Y) / P(X) * P(Y))
double XandY = (double) 1210738 / N;
double X = (double) 67360790 / N;
double Y = (double) 1871676 / N;
System.out.println(Math.log(XandY / (X * Y)) / Math.log(10));
System.out.println("------");
// contingency table notation as on www.collocations.de
long o11 = 1210738;
long o12 = 67360790;
long o21 = 1871676;
long c1 = o11 + o21;
long r1 = o11 + o12;
double e11 = ((double) r1 * c1 / N);
double frac = (double) o11 / e11;
System.out.println(Math.log(frac) / Math.log(10));
}
}
Let write it in the same terms
long o11 = 1210738;
long o12 = 67360790;
long o21 = 1871676;
long N = 1024908267229L
The first equation is
XandY = o11 / N;
X = o12 / N;
Y = o21 / N;
so
XandY / (X * Y)
is
(o11 / N) / (o12 / N * o21 / N)
or
o11 * N / (o12 * o21)
Note there is no adding going on.
The second equation is rather different.
c1 = o11 + o21;
r1 = o11 + o12;
e11 = ((double) r1 * c1 / N);
frac = (double) o11 / e11;
so
e11 = (o11 + o21) * (o11 + o12) /N;
frac = (o11 * N) / (o11^2 + o11 * o12 + o21 * o11 + o21 * o12);
I would expect these to be different as mathematically they are not the same.
I suggest you write what you want as maths first, and then find the most efficient way of coding it.
I have some lines of code that produces a number after calculation which is currently in JavaScript and here is the code:
if ( y2 != y1 )
{
// calculate rate
var f;
var y;
if ( y2 > y1 )
{
f = cpi[y2] / cpi[y1];
y = y2 - y1;
}
else
{
f = cpi[y1] / cpi[y2];
y = y1 - y2;
}
var r = Math.pow(f, 1/y);
r = (r-1)*100;
r = Math.round(r*100) / 100;
System.out.println( "number: " + r.toFixed(2) + "%." );
}
I converted the above JS code to Java and here is the code:
DecimalFormat decimalFormat = new DecimalFormat("0.##");
if (cpi[to] != cpi[from]) {
double f, y;
if (cpi[to] > cpi[from]) {
f = cpi[to] / cpi [from];
y = to - from;
}
else {
f = cpi[from] / cpi[to];
y = from - to;
}
q = Math.pow(f, 1/y);
q = (q-1)*100;
q = Math.round(q*100)/100;
Toast.makeText(getApplicationContext(), "number: " + String.valueOf(decimalFormat.format(q)), 2000).show();
}
The JavaScript code produces: number: 2.39
While the Java code produces number: 2
Why am I getting two different value? I will post what cpi[to], cpi[from], to and from values are if needed.
In this line
q = Math.round(q*100)/100;
both operands of the division operation are integral, therefore the result is also an integral type. Use 100.0 as the divisor to coerce the result to a double.
what is q type?
try to put 100.0 also
If you devide two integers in java the result is integer. Every operation with double and integer or with two doubles creates double.
1)In this line
1)q = Math.round(q*100)/100;
2)you are deviding two integers, so it has same output as:
2)q = (int) (Math.round(q*100)/100);
3)you can use casting to double for example:
3)q = Math.round(q*100)/(double)100;
4)or using the 100.0 which makes this number double:
4)q = Math.round(q*100)/100.0;
5)this should work too, because first the result of Math.round is converted to double and then devided by 100:
5)q = (double)Math.round(q*100)/100;
6)However this WILL NOT work, because first Math.round is devided by 100 and it creates integer, so the result of this operation is rounded down and AFTER then casted to double. So it will be double but still rounded down, because it was rounded before it becomes double.
6)q = (double)(Math.round(q*100)/100);
Most likely your issue is Math.round(double) returns a long value. So d would contain a long instead of a double at that point.