printing the percent completed - java

I am trying to divide 2 Long's in order to find the percentage. However, I only get 0.0% or when they are equal, 100.0%. This is what I am doing
long size =
long mem =
double avg = (double)(size / mem) * 100;

You're doing long division which truncates the fractional part of the number. At least one of the operands is required to be a double to produce a non-zero double, You could do:
double avg = (double)size / mem * 100;
The numerator now becomes a double as a cast has high precedence than the division operator /.

If you want to avoid long decimal numbers you can use.
long percentage = 100 * size / mem; // as an integer.
If you want one decimal place you can do
double percentage = (1000 * size / mem) / 10.0;

Related

Decimal separator in long (Java/Spring)

I need to put the decimal separator point in a Long, I have tried in several ways, but I need it to be dynamic since the decimal separator can change, I have tried with DecimalFormat format = new DecimalFormat("###.##"); but this is not dynamic and it doesn't work the way I wanted it to
Example 1
long amount = 123456;
int decimal = 2;
The result should be Double newAmount = 1234.56
Example 2
long amount = 123456;
int decimal = 4;
The result should be Double newAmount = 12.3456
If I understand correctly, this is what you are trying to achieve:
Long amount = 123456;
int decimal = 2;
double newAmount = amount.doubleValue();
newAmount = newAmount / Math.pow(10, decimal);
Use the pow method of java.lang.math to calculate the power of a number.
Be careful to declare your variable as an object of type Long and not a primitive type if you want to use one of its functions.
As suggested, it is even simpler to just use a double variable instead of a long from the start:
double amount = 123456;
int decimal = 2;
amount = amount / Math.pow(10, decimal);
You can get the required number by dividing the given number by 10 ^ decimalPlaces e.g.
public class Main {
public static void main(String[] args) {
// Test
System.out.println(getNum(123456, 2));
System.out.println(getNum(123456, 4));
}
static double getNum(long val, int decimalPlaces) {
return val / Math.pow(10, decimalPlaces);
}
}
Output:
1234.56
12.3456
All the other answers suggest converting to double and then scaling by powers of 10 before displaying. This will result in some unexpected results because of a loss of precision in the scaling operation. For the complete, gory details on why, please read
What Every Computer Scientist Should Know About Floating-Point Arithmetic and
Is Floating Point Broken?
As to your problem, you should be doing the work using BigDecimal. Converting from long (or Long) to BigDecimal does not lose precision, and will always produce the expected results.
BigDecimal even has a method to do the scaling for you:
long amount = 123456;
int decimal = 2;
BigDecimal n = BigDecimal.valueOf(amount).scaleByPowerOfTen(-decimal);
Output:
1234.56

Convert double into BigRational (two BigInteger for numerator/denominator)

I have a custom made BigRational class in java.
It is implemented as two BigInteger, representing numerator and denominator.
I have a "from string" method that take input in the form "-1234/43"
but I would like to implement a from double/from float;
I'm not scare of generating a very large number, but I would like to keep all the precision present in the floating point representation; thus if I converted them in some decimal representation I would lose precision thanks to rounding.
-How do I generate a pair of BigIntegers that interpreted as numerator/denominator represents the same exact number as a given float/double?
(Hopefully by being in Java I do not need to worry about bigendian/littleendian, but I would like a confermation too)
So, thanks to a good friend I have found a good solution, so I will post it here for anyone in need.
It is not using any string representation so it should also be quite on the fast side.
I have tested it "reasonably" and It seams to work and to keep the exact representation.
Of course, we should still add some 'if' to handle NANs.
final static int mantissaBits=53;
public static BigRational from(double num){
int exponent=Math.getExponent(num);
long man=Math.round(Math.scalb(num, mantissaBits-exponent));
long den=Math.round(Math.scalb(1.0, mantissaBits-exponent));
return new BigRational(BigInteger.valueOf(man),BigInteger.valueOf(den));
}
Caveat: Not all numbers are rational, e.g. PI is not a rational number. However, given that double (and float) have limited precision, there are a limited number of digits in a floating-point value, so you can always find a rational number for that. E.g. Math.PI is a double with the value 3.141592653589793. That number is the rational number 3_141_592_653_589_793 / 1_000_000_000_000_000.
Understanding the caveat that floating-point values aren't accurate, you can find the rational number with the help of BigDecimal, then normalize the rational number using BigInteger.gcd().
Like this:
static void printAsRational(double value) {
printAsRational(BigDecimal.valueOf(value));
}
static void printAsRational(float value) {
printAsRational(new BigDecimal(Float.toString(value)));
}
static void printAsRational(BigDecimal value) {
BigInteger numerator, denominator;
if (value.signum() == 0) {
// Zero is 0 / 1
numerator = BigInteger.ZERO;
denominator = BigInteger.ONE;
} else {
BigDecimal bd = value.stripTrailingZeros(); // E.g. 1.20 -> 1.2
if (bd.scale() < 0)
bd = bd.setScale(0); // E.g. 1.7e3 -> 1700
numerator = bd.unscaledValue(); // E.g. 1.25 -> 125
denominator = BigDecimal.valueOf(1, -bd.scale()).toBigInteger(); // E.g. 1.25 -> 100
// Normalize, e.g. 12/8 -> 3/2
BigInteger gcd = numerator.gcd(denominator);
if (! gcd.equals(BigInteger.ONE)) {
numerator = numerator.divide(gcd);
denominator = denominator.divide(gcd);
}
}
System.out.println(value + " = " + numerator + " / " + denominator);
}
Tests
printAsRational(Math.PI);
printAsRational(Math.E);
printAsRational(1.25);
printAsRational(1);
printAsRational(0);
printAsRational(-1.25);
printAsRational(1.25e9);
printAsRational(1.25e-9);
Output
3.141592653589793 = 3141592653589793 / 1000000000000000
2.718281828459045 = 543656365691809 / 200000000000000
1.25 = 5 / 4
1.0 = 1 / 1
0.0 = 0 / 1
-1.25 = -5 / 4
1.25E+9 = 1250000000 / 1
1.25E-9 = 1 / 800000000

Generate Random X.XXX numbers between [-2, 2]

x = rd.nextInt((4000) - 2000) / 1000.0;
This is generating numbers between [0, 2] to the thousandth decimal which is what I want, I just also need negative number so the range of numbers generated is between [-2, 2].
The problem you are facing is integer arithmetic, which truncates the fractional part of the result. Use rd.nextDouble() instead so the arithmetic results are double, which retains the fractional part.
However, to round to 1/100ths, you can use integer arthmetic to your advantage.
Your question has the text to the hundredth decimal, so here's that solution:
x = (int)(((rd.nextDouble() * 4) - 2) * 100) / 100d;
But your title mentions X.XXX, so here's that solution:
x = (int)(((rd.nextDouble() * 4) - 2) * 1000) / 1000d;
To unravel what's going on here:
generate random double between 0.000000 and 1.000000
multiply by the scale of the range, so we get a number between 0.000000 and 4.000000
subtract 2, so we get a number between -2.000000 and 2.000000
multiply by 1000, so we get a number between -2000.000000 and 2000.000000
cast to int to truncate the fraction, so we get a int between -2000 and 2000
divide by 1000d (which is a double), so we get a double between -2.000 and 2.000
Floating point numbers do not always have a precise number of digits. Also, the third decimal place is called thousandths (the hundredth decimal would be the second digit after the .). I think you know this because you are dividing by a thousand. So, step one: generate a single random value between 0 and 4 as a double. Step two: Subtract two and convert to a formatted String (so you can control the number of digits).
double d = (rd.nextDouble() * 4) - 2;
String x = String.format("%.3f", d);
You can generate a random float and then use a modulo to truncate it to the hundredth decimal place.
int min = -2;
int max = 2;
Random rand = new Random();
float ret = rand.nextFloat() * (max - min) + min;
return ret - (ret % 0.01);
You can generate random number on a range [0,4] and then simply subtract 2 from the result:
x = (rd.nextInt(4000) / 1000.0) - 2;

How to prevent double from rounding up to two decimal

I'm trying to calculate a percentage(9% tax) of a item
double amount = 55.4;
double total = amount * 0.09;
System.out.printf ("%f \n", total);
System.out.printf ("%.2f \n", total);
Returns
4.986000
4.99
How do I make it return 4.98?
Thanks!
Use BigDecimal instead of double.
double is floating point, which cannot accurately represent all fractional amounts, hence the "rounding" problem that you are.experiencing.
BigDecimal is arbitrary-precision, and so doesn't have that problem.
If you want to chop off the thousands place multiple your total by 100 and cast it to an int, then divide it by 100 and cast it to a double:
double amount = 55.4;
double total = amount * 0.09;
int truncated = (int) (total * 100);
double val = truncated * .01;
System.out.printf("%.2f\n", val);
This will give you:
4.98
This can also be done with
double val = Math.floor(total * 100) / 100;
System.out.printf("%.2f\n", val);

Method not dividing for desired double value

In my program, I'm trying to divide two double values and return the quotient of it. Like this:
public double getMonthlyPayment(){
double monthlyRate = AnnualInterestRate / 1200;
double numberOfMonths = numberOfYears * 12;
double dividend = (loanAmount * monthlyRate);
double divisor = (1 - Math.pow(1+monthlyRate, -numberOfMonths));
return dividend / divisor;
}
Currently it's not returning the value I'm expecting. It's only returning the dividend value and not the value when dividend is divided by divisor.
For example, since this is a loan calculator, I need a loan of $2000 with 5% interest for 2 years. In order to achieve this value, you would need to use a certain equation.
I've made my own form of that equation in the code above and it's only returning the dividend value, which is (loanAmount * monthlyRate), instead of returning dividend value divided by (1 - Math.pow(1+monthlyRate, -numberOfMonths))
Could someone help me with this?
Thanks in advance for any help.
Your code doesn't show, but if AnnualInterestRate is an int, then the division by 1200 is done using integer logic, and the result (an integer) is then coerced to double. Specifying 1200.0 will force coercion of AnnualInterestRate to double before the division.
We do not know data types of all variables in your question. If the data type of right side is integer and left side is double, explicitly cast the result to double
Correct code should be:
public double getMonthlyPayment(){
double monthlyRate = (double)AnnualInterestRate / 1200;
double numberOfMonths = (double) numberOfYears * 12;
double dividend = (loanAmount * monthlyRate);// Assuming loanAmount is double
double divisor = (1 - Math.pow(1+monthlyRate, -numberOfMonths));
return dividend / divisor;
}

Categories