Is there a way I can compare (>, <, >=, <=, !=, ==) a decimal represented as a long and int?
If the number is 3214.21 then it would be represented in a class like this
long units = 321421;
int precision = 2;
// to get the original number I would do units * 10^precision
I would like to be able to do something similar to BigDecimal's compareTo() method. So greater than returns 1, equals returns 0, less than returns -1.
What I am currently doing does not work for some cases. The code that causes it to function that way is outlined below. The method is more or less a proof of concept.
public int compareTo(Money other) {
if (precision == other.getPrecision()) { // fast check if precision is the same
if (units > other.getUnits()) return 1; // we forgot to inverse/flip here. will be an issue for non-decimal
else if (units < other.getUnits()) return -1;
else return 0; // least likely
}
int intX = (int) (units / (Math.pow(10, precision))); // converted units whole numbers to int
int fractionX = (int) (units % (Math.pow(10, precision))); // converts the decimal as an int
int intY = (int) (other.getUnits() / (Math.pow(10, other.getPrecision()))); // converted units whole numbers to int
int fractionY = (int) (other.getUnits() % (Math.pow(10, other.getPrecision()))); // converts the decimal as an int
System.out.println("Test: i " + intX + "| f " + fractionX + "| u " + units + "| p " + precision);
System.out.println("Test2: i " + intY + "| f " + fractionY + "| u " + other.getUnits() + "| p" + other
.getPrecision
());
if (intX > intY) return 1;
else if (intX < intY) return -1;
else {
if (fractionX > fractionY) return 1; // this is where the logic fails
if (fractionX < fractionY) return -1;
else return 0;
}
}
Here is my test along with output
System.out.println(MoneyFactory.fromString("0.3").compareTo(MoneyFactory.fromString("0.29")));
System.out.println(MoneyFactory.fromString("13").compareTo(MoneyFactory.fromString("0.31456789")));
System.out.println(MoneyFactory.fromString("0.2999").compareTo(MoneyFactory.fromString
("0.3")));
Output
Test: i 0| f 3| u 3| p 1
Test2: i 0| f 29| u 29| p2
-1
Test: i 13| f 0| u 13| p 0
Test2: i 0| f 31456789| u 31456789| p8
1
Test: i 0| f 2999| u 2999| p 4
Test2: i 0| f 3| u 3| p1
1
The simplest solution would be to convert one number to the common precision level and then compare the numbers. If they are the same use `number with bigger precision' logic (in pseudo code):
return (number1 == number2) ? [number with bigger precision logic] : number1 - number2
In Java code
class Money {
long units;
int precision;
public Money (long un, int prec) {
units = un;
precision = prec;
}
public int compareTo(Money other) {
int preResult = this.precision - other.precision;
long first = (preResult > 0) ? ((long)(this.units / Math.pow(10, preResult))) : this.units;
long second = (preResult < 0) ? ((long)(other.units * Math.pow(10, preResult))) : other.units;
return (first == second) ? preResult : Long.compare(first, second);
}
public static void test() {
Money first = new Money(2345L, 4);
Money second = new Money(234567L, 6);
System.out.println(first.compareTo(second));
}
}
EDIT: There was an error in the code. Changing the 1 in both tenary checks to 0 fixes this issue
I think you just do it like this:
public int compareTo(Money other) {
return Double.compare(units/Math.pow(10, precision), other.getUnits()/Math.pow(10, other.getPrecision()));
}
Related
public class main {
public static void main(String[] args) {
aboveAverageTester();
}
public static int aboveAverage(int a, int b, int c, int d, int e, int f) {
//This method computes the average of the parameters
//and then returns how many of the parameters are above the average.
int avg = (a + b + c + d + e + f) / 6;
int above = 0;
if (a > avg) {
return a;
}else if (b > avg) {
return b;
}else if (c > avg) {
return c;
}else if (d > avg) {
return d;
}else if (e > avg) {
return e;
}else if (f > avg) {
return f;
}else{
return a + b + c + e + f;
}
}
public static int aboveAverageTester() {
int aboveAverage = aboveAverage(10, 10, 10, 10, 45, 50);
System.out.println(aboveAverage);
return aboveAverage;
}
}
I know the aboveAverage method logic may be completely off, but I'm getting a problem when I'm trying to return how many of the parameters are above the average.
From my code, I believe that when you keep returning like a, b ,c.. etc after each if-- it's just 1 instance and not adding to the list of others that my be larger than the average.
I'm trying to preform this without printing anything in this method, only logic.
I know I kind of messed up, also, at the bottom of the aboveAvg method by adding all the a,b,c,d,e,f and not just creating a list from them.
Can anyone give me an idea of how to approach this?
Your method is returning one of the values, not the count. It also truncates the average when the sum a + b + c + d + e + f is not divisible by six.
You can fix this by using double for the average, dividing by 6.0 to force double result type, and then counting the number of above average numbers with conditional operator:
double avg = (a + b + c + d + e + f) / 6.0;
return (a > avg ? 1 : 0)
+ (b > avg ? 1 : 0)
+ (c > avg ? 1 : 0)
+ (d > avg ? 1 : 0)
+ (e > avg ? 1 : 0)
+ (f > avg ? 1 : 0);
To count the number of elements above the average, you can loop on each one and increment a counter as the condition is true :
int aboveAverage = 0;
List<Integer> numbers = Arrays.asList(a,b,c,d,e,f);
for (int number : numbers){
if (number > avg){
aboveAverage++;
}
}
return aboveAverage;
With Java 8, you could write it in a less verbose way :
long aboveAverage = Arrays.asList(a,b,c,d,e,f).stream()
.filter(n-> n > avg)
.count();
Not sure if I got your question completely, but I guess you want to count how many values are above the average.
So instead of returning the value when the if statement holds true, you should increment the counter like this:
if (a > avg) {
above++;
}
I have a homework assignment where I have to covert any base to base 10. I have some given numbers, which are the "basen". I have to convert those bases to base 10. The only part that I am stuck in is this part of the code:
answer = ; // Not sure what I have to put in here
I have seen some other posts about converting to base ten, but I am just not sure how to how to incorporate them into my code.
public class BaseN {
public static final int BASEN_ERRNO = -1;
public static int digit = 0;
public static void main(String[] argv) {
basen(512, 6);
basen(314, 8);
basen(49, 5);
basen(10101, 2);
}
public static void basen(int n, int b) {
int ans = basen(n, b, 1, 0);
if (ans == BASEN_ERRNO)
System.out.println(n + " is not a valid base-" + b + " number");
else
System.out.println(n + " base-" + b + " = " + ans + " base-10");
}
public static int basen(int number, int base, int placevalue, int answer) {
if (number == 0) return answer;
digit = number % 10;
if (digit >= base) return BASEN_ERRNO;
answer = 1;// not sure what to put here
number = 0;
placevalue = 0;
return basen(number, base, placevalue, answer);
}
}
You could look at a k length number of base n like this:
x(0)*n^(k-1) + x(1)*n^(k-2) + ... + x(k-1)*n^1 + x(k)*n^0
Where x(0), x(1), ..., x(k) is the digit at position k from the left.
So, if you are trying to convert, say, 101 base 2 to base 10 you would do the following :
1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 4 + 0 + 1 = 5 base 10
say you want to convert the number 352 from base 6:
3 * 6^2 + 5 * 6^1 + 2 * 6^0 = 108 + 30 + 2 = 145 base 10
What you're looking for code wise is something like this :
int[] digits = {3, 5, 2};
int base = 6;
int answer = 0;
for(int i = digits.length - 1; i >= 0; i--)
{
answer += digits[i] * Math.pow(base,digits.length-i-1);
}
return answer;
which will return 145.
Hopefully even though my implementation is iterative you should be able to apply it to your recursive implementation as well.
You can implement the following algorithm. Lets say you are given String number which represents the number you want to convert to decimal form and int base which represents the base of given number. You can implement function int convertToNumber(char c); which accepts one character representing one digit from your number and will map characters to numbers like this:
0 -> 0,
1 -> 1,
... ,
A-> 10,
B -> 11,
... ,
F -> 15,
...
Then you just iterate through your given string and multiply this functions output with base to the power of iteration. For example, convert number A32(hexadecimal):
A32 = convertToNumber(A) * b ^ 2 + convertToNumber(3) * b ^ 1 + convertToNumber(2) * b ^ 0 = 10 * 16 ^ 2 + 3 * 16 ^ 1 + 2 * 16 ^ 0 = 10 * 16 * 16 + 3 * 16 + 2 = 2610 (decimal).
public class BaseConvert {
public static int convertDigitToNumber(char c) throws Exception {
if(c >= '0' && c <= '9') return c - '0';
if(c >= 'A' && c <= 'Z') return c - 55;
if(c >= 'a' && c <= 'z') return c - 97;
throw new Exception("Invalid digit!");
}
public static int convertToBase(String number, int base) throws Exception {
int result = 0;
for(int i = 0; i < number.length(); i++){
result += convertDigitToNumber(number.charAt(i)) * (int)Math.pow(base, number.length() - i - 1);
}
return result;
}
public static void main(String[] args) {
try{
System.out.println(convertToBase("732", 8));
System.out.println(convertToBase("A32", 16));
System.out.println(convertToBase("1010", 2));
}catch (Exception e) {
System.out.print(e);
}
}
}
I just solve this but want know more efficient way to do matrix multiplication
M = | 1 0 3 |
| 1 0 2 |
| 0 5 0 |
f[n] = M^n
I have implemented using Exponentiation_by_squaring
Is there more efficient then this ?
I guess, this is actually more suitable for math as there's a closed form solution. It's system of Linear homogeneous recurrence relations with constant coefficients.
Another posibility: You could speed up the program twice by deriving a formula for two steps, i.e., express RR(i) etc. via RR(i-2), etc.
And this can be repeated, so you can jump much faster.
One problem is that your calculations are overflowing. If you run it for K=1 and J=9, you get -334328541#510576792#-817751931.
The easiest fix for that is to do % 1000000006 in calculateProduction.
About efficiency, I would look at this problem as performing matrix multiplications.
You start with the vector (i.e. 1*3 matrix):
3 1 0
And at each step you multiply it (mod 1000000006) with the matrix:
1 1 0
0 0 5
3 2 0
Let's call the vector V and the matrix M. Basically you need to calculate V*MN. Since matrix multiplication is associative, you can calculate MN first, and do that recursively:
MN = (MN/2)2 if N is even, or
MN = M*(M[N/2])2 if N is odd
You don't need to calculate MM. This is why:
PP[i] = 5*MM[i-1] = 5*(RR[i-2] + 2*PP[i-2])
RR[i] = RR[i-1] + 3*PP[i-1] = (RR[i-2] + 3*PP[i-2]) + 3*PP[i-1]
See? You don't need to calculate MM at each step. This should be the algorithm:
public class RecurrenceMachine {
private static final int max = 1000000006;
public String calculate(int k, int j) {
long n = k * j;
if (n < 1)
return "error";
long RRi2 = 3;
long PPi2 = 0;
long RRi1 = 3 + 3 * PPi2;
long PPi1 = 5 * 1;
if (n == 1)
return RRi1 + "##" + (RRi2 + 2 * PPi2) + "##" + PPi1;
Long PPi = (long) 0, RRi = (long) 0, temp;
int i;
for (i = 2; i <= n; i++) {
temp = RRi2 + 2 * PPi2;
PPi = 5 * temp;
if (PPi >= max)
PPi %= max;
RRi = temp + PPi2 + 3 * PPi1;
if (RRi >= max)
RRi %= max;
RRi2 = RRi1;
PPi2 = PPi1;
RRi1 = RRi;
PPi1 = PPi;
}
return RRi + "##" + (RRi2 + 2 * PPi2) % max + "##" + PPi1;
}
}
I tried only with small values and it seems to work.
I am trying to replicate a list of conversions from kg to lbs and vice versa. I've found my desired code for output and functionality, but I am missing something to align my values to the right of the column.
Here is my code:
import java.text.*;
public class KilosTwoColumn {
public static void main(String[] args) {
System.out.println("Kilograms" + "\t" + "Pounds" + "\t" + " | " + "\t" + "Pounds" + "\t" + "Kilograms");
int count = 0;
while (count < 100) {
int kilos = count * 2 + 1;
int pounds2 = (count + 4) * 5;
double pounds = kilos * 2.2;
double kilos2 = pounds2 * .453;
DecimalFormat df = new DecimalFormat("#.#");
//if (count > 1 && count < 98) {
//System.out.println("...");
//break;
//}
System.out.printf("%-17d %.1f | %7d %.2f%n", kilos, pounds, pounds2, kilos2);
count++;
}
}
}
I am also trying to create a break in the list three rows in and resume the last two.
The problem is that you are not specifying a width for the float values, just the number of decimal places.....
For example, consider "%-17d %.1f ..." which will set the second value to be a float value with 1 decimal place, but no indication of how much space to occupy. By changing that to "%-17d %12.1f it will occupy 12 characters, with 1 decimal.
Try something like:
public class KilosTwoColumn {
public static void main(String[] args) {
System.out.printf("%12s %12s | %7s %12s\n", "Kilograms", "Pounds", "Pounds", "Kilograms");
int count = 0;
while (count < 100) {
int kilos = count * 2 + 1;
int pounds2 = (count + 4) * 5;
double pounds = kilos * 2.2;
double kilos2 = pounds2 * .453;
DecimalFormat df = new DecimalFormat("#.#");
//if (count > 1 && count < 98) {
//System.out.println("...");
//break;
//}
System.out.printf("%12d %12.1f | %7d %12.1f\n", kilos, pounds, pounds2, kilos2);
count++;
}
}
}
For me, the above process outputs:
Kilograms Pounds | Pounds Kilograms
1 2.2 | 20 9.1
3 6.6 | 25 11.3
....
199 437.8 | 515 233.3
In Java, I am trying to find a way to convert a float number into a fraction string. For example:
float num = 1.33333;
String numStr = Convert(num); // Should return "1 1/3"
float num2 = 1.333;
String numStr2 = Convert(num2); // Should also return "1 1/3"
float num3 = 0.5;
String numStr3 = Convert(num3); // Should return "1/2"
float num4 = 2.25;
String numStr4 = Convert(num4); // Should return "2 1/4"
Any ideas how to do this in Java?
The simplest approach might be to use trial and error.
public static String toFraction(double d, int factor) {
StringBuilder sb = new StringBuilder();
if (d < 0) {
sb.append('-');
d = -d;
}
long l = (long) d;
if (l != 0) sb.append(l);
d -= l;
double error = Math.abs(d);
int bestDenominator = 1;
for(int i=2;i<=factor;i++) {
double error2 = Math.abs(d - (double) Math.round(d * i) / i);
if (error2 < error) {
error = error2;
bestDenominator = i;
}
}
if (bestDenominator > 1)
sb.append(' ').append(Math.round(d * bestDenominator)).append('/') .append(bestDenominator);
return sb.toString();
}
public static void main(String... args) {
System.out.println(toFraction(1.3333, 1000));
System.out.println(toFraction(1.1428, 1000));
for(int i=1;i<100000000;i*=10) {
System.out.println("PI "+i+": "+toFraction(3.1415926535897932385, i));
}
}
prints
1 1/3
1 1/7
PI 1: 3
PI 10: 3 1/7
PI 100: 3 14/99
PI 1000: 3 16/113
PI 10000: 3 16/113
PI 100000: 3 14093/99532
PI 1000000: 3 140914/995207
PI 10000000: 3 244252/1725033
Look into chain fractions. This allows you to determine denominator and fraction within a given accuracy.
For Pi you can get 22/7 or 355/113 depending on when you choose to stop.
This might be of help:
http://www.merriampark.com/fractions.htm
Otherwise you'd need some way of telling Convert() how far out you want to take things. Maybe a maximum reduced demoninator or something like that. That way you'll get "1 1/3" for both of the first two examples you have above rather than "1 33333/100000" for the first and "1 333/1000" for the second.
Extract the fractional part of the number (for example, ((int) 0.5 + 1) - 0.5, then divide one by the result (1 / 0.5). You'll get the denominator of the fraction. Then cast the float to an int, and you'll get the integer part. Then concatenate both.
It's just a simple solution, and will work only if the numerator of the fraction is 1.
double n = 1.2f;
int denominator = 1 / (Math.abs(n - (int) n - 0.0001)); //- 0.0001 so the division doesn't get affected by the float point aproximated representation
int units = (int) n;
int numerator = units * denominator + 1;
System.out.println("" + numerator + "/" + denominator); //6/5
System.out.println("" + units + " 1/" + denominator); //1 1/5
Assume you have "0.1234567", then count how many numbers after the decimal point (which is 7). then multiply the number with 10 ^ 7, now you have "1234567".
divide 1234567 over 10 ^ 7. Then, simplify the fraction using the GCD of the two numbers.
0.1234567 * 10000000 = 1234567
=> 1234567 / 10000000
=> System.out.println(1234567 / gcd(1234567,10000000) + "/" + 10000000/gcd(1234567,10000000));
Modified the FOR loop to break the loop, when the best denominator is already identified.
if (error2 == 0) break;
public static String toFraction(double d, int factor) {
StringBuilder sb = new StringBuilder();
if (d < 0) {
sb.append('-');
d = -d;
}
long l = (long) d;
if (l != 0) sb.append(l);
d -= l;
double error = Math.abs(d);
int bestDenominator = 1;
for(int i=2;i<=factor;i++) {
double error2 = Math.abs(d - (double) Math.round(d * i) / i);
if (error2 < error) {
error = error2;
bestDenominator = i;
if (error2 == 0) break;
}
}
if (bestDenominator > 1)
sb.append(' ').append(Math.round(d * bestDenominator)).append('/') .append(bestDenominator);
return sb.toString();
}
public static void main(String... args) {
System.out.println(toFraction(1.3333, 1000));
System.out.println(toFraction(1.1428, 1000));
for(int i=1;i<100000000;i*=10) {
System.out.println("PI "+i+": "+toFraction(3.1415926535897932385, i));
}
}