Rounding Off to 2 decimal places giving issues while summing up - java

Getting the following sets of numbers -->
[5.1429,5.1429,5.1429,5.1429,5.1429,5.1429,5.1426]
[0.8333,0.8333,0.8333,0.8333,0.8333,0.8335]
When added, these give a whole number.
Now we have to display these numbers after rounding to 2 decimal places which look like this -->
[5.14, 5.14, 5.14, 5.14, 5.14, 5.14, 5.14]
[0.83, 0.83, 0.83, 0.833, 0.83, 0.83]
Which is not summing up to a whole number. This is causing the whole total to come something like 99.96 or 101.01.
Is there a way we can round the numbers so that the total comes to a whole number.
I am not looking for a way to round off the sum. i am looking for a way to manipulate the already rounded numbers (like 5.14,5.14.. etc) so that they give a whole number. (if there is a way.. that is :) )

You would introduce the smallest absolute rounding error - while keeping the total sum intact - if you sort the inputs by decreasing third decimal and round everything down, except for just enough numbers to reach the target.
As a simple example:
input
0.132, 0.226, 0.257, 0.385 // sums up to 1.00
sort by 3rd decimal (descending)
0.257, 0.226, 0.385, 0.132
round everything down
0.25, 0.22, 0.38, 0.13 // sums up to 0.98
round up just enough to reach a whole number
0.26, 0.23, 0.38, 0.13 // sums up to 1.00
In code (untested):
public void printRounded(double[] ds) {
// create wrapper objects
int n = ds.length;
Wrapper[] ws = new Wrapper[n];
for (int i = 0; i < n; i++)
ws[i] = new Wrapper(i, (int)(ds[i] * 1000) % 10, (int)(ds[i] * 100));
// sort by third decimal, descending
Arrays.sort(ws, new Comparator<Wrapper>() {
public int compare(Wrapper o1, Wrapper o2) {
return o2.thirdDecimal.compareTo(o1.thirdDecimal);
}
});
// find number of elements that must be rounded up and increment
int sum = 0;
for (int i = 0; i < n; i++)
sum += ws[i].prefix;
int numberToIncrement = 100 - (sum % 100);
for (int i = 0; i < numberToIncrement ; i++)
ws[i].prefix++;
// sort back to input order
Arrays.sort(ws, new Comparator<Wrapper>() {
public int compare(Wrapper o1, Wrapper o2) {
return o1.index.compareTo(o2.index);
}
});
// print values
for (int i = 0; i < n; i++) {
System.out.println(ws[i].prefix / 100 + "." ws[i].prefix % 100);
}
}
private class Wrapper {
public Wrapper(int index, int thirdDecimal, int prefix) {
this.index = index;
this.thirdDecimal = thirdDecimal;
this.prefix = prefix;
}
public int index;
public int thirdDecimal;
public int prefix;
}
Instead of using the custom formatting you could of course convert the ints back to double and use standard formatting.

If I round the result, I get a whole number.
public static void main(String... ignored) {
sum(5.1429, 5.1429, 5.1429, 5.1429, 5.1429, 5.1429, 5.1426);
sum(0.8333, 0.8333, 0.8333, 0.8333, 0.8333, 0.8335);
}
private static void sum(double... xs) {
double sum = 0;
for (double x : xs) {
sum += x;
}
System.out.printf("sum was %.2f%n", sum);
}
BTW: If you know you expect a whole number, you should round to a whole number, not two decimal places.

There's no way to do this unless you abandon the firm requirement
for rounding your numbers (to 2 decimal places) and allow for
(a) truncating your numbers (after the 2nd decimal place);
(b) rounding up/down when actually you need to round down/up.
If you allow for these operations (on some of the numbers) instead of
rounding all of them by the book, then most probably you can come up
with some algorithm which would give you the same (integral) sum even
after the rounding/truncation operations is applied on the original
numbers. But again, this is not really rounding (as we know it from math).

One way you could do it would be to round to two decimal places then take each number an multiply it by a hundred and divide it by the sum of the numbers. This should get you closer to 100 and if you iterate over that enough times your result should approach 100. So basically (pseudcode)
lsum = 0
vecNums = //previous numbers
while abs(nsum -100) >.01
for i in vecNums
i = (i*100)/sum(vecNums)
return vecNums

You could just sum them up as you did, and then round the final sum as well.

You can take a look at the Math.round(double a) method
System.out.println(Math.round(12.51));//Yields 13
System.out.println(Math.round(12.49));//Yields 12
System.out.println(Math.round(12.50));//Yields 13
from Round off in JAVA

Related

partitioning integer into almost equal elements

Is there a function somewhere that divides integer or decimal numbers into parts that are as equal as possible and sum up to the input value?
I'm looking for something that would work like that:
devide(4,2) -> {2,2} (2+2=4, 2 and 2 are equal)
devide(6,4) -> {2,2,1,1} (2+2+1+1=6, no way to make these numbers closer to each other)
I know I can do it myself but I'm looking for some library function.
I've never heard of a library that does that, but it'es quite easy. Just put the quotient in each cells of an array the size of the divisor, then put the remainder in each cell.
Example:
public static int[] divide(int n, int d){ //d for divisor
int[] res = new int[d];
int qu = n/d; //quotient
int rm = n%d; //remainder
for(int i=0; i<d; i++){
res[i] = qu;
if(i < rm){
res[i]++;
}
}
return res;
}

Calculating a BigDecimal results in inaccurate answer

So I just wanted to screw around to see if I can make it so I can calculate E, but instead have it so I can have dynamic degrees of precision. While I did technically accomplish it, no matter what int i put in for the variable PRECISION, the last few numbers are always different from what the actual value of E is suppose to be. I'm not entirely sure why, but help would be appreciated.
import java.math.BigDecimal; //To use for calculating E
public class ComputeE {
public static double calcDenominator(int n)
{
double denominator = 1.0; //Start the BigInt with 1
for(int i = 1; i < n; i++) // Run n-1 amount of times
{
denominator = denominator * i; // Multiply BigInteger by the BigInteger obtained with the int value i
}
return denominator;
}
public static void main(String[] args) {
BigDecimal e = new BigDecimal(0.0);
int PRECISION = 15;
int iterations = 0;
for(int i = 0; i < PRECISION; i++)
{
iterations++;
BigDecimal numerator = new BigDecimal(1.0); // to divide, we need two BigDecimals, the numerator is 1
BigDecimal factorial = new BigDecimal(calcDenominator(i)); // the denominator is i! which we get from calling the factorial method
factorial = numerator.divide(factorial, PRECISION, BigDecimal.ROUND_UNNECESSARY); // compute 1/i!, note divide is overloaded, this version is used to
// ensure a limit to the iterations when division is limitless like 1/3
e = e.add(factorial); // add the latest 1/i! to e
}
System.out.println("Computed value of e : " + e);
System.out.println("Expected value of e : " + Math.E);
}
}
Rounding is necessary here. Use something like HALF_EVEN. Even better, use the enum value RoundingMode.HALF_EVEN, because the integer constants for rounding mode are deprecated.
In calcDenominator, change your for loop condition to i <= n, or else you'll add 1 one too many times in main and you'll get a value that's 1 too high.
You can use BigDecimal.ONE to initialize numerator. This doesn't affect the result, but why create an unnecessary object? Same comment on the initialization of e, except with BigDecimal.ZERO.
You are using the first PRECISION terms of an infinite series (Maclaurin Series) that approximates e, an irrational number. There is an error term when you cut off the for loop, and that is expected mathematically. With the above changes, and bumping PRECISION to 50, I get the following, which looks sufficiently precise.
Computed value of e : 2.71828182845904523536028747135266249775496954201584
Expected value of e : 2.718281828459045
It is precise, despite using the double constructor for BigDecimal because the significant digits for a double start with the first non-zero bit, so even if you're calculating 1/n! for large n, the significant digits are good enough for adding to the existing approximation for e.

Extracting a digit from a number ranging from 0 to 99999

I am working at a programm right now where I need to sort an array of numbers ranging from 0 to 99999. In order to do so, one part of the task is to extract the digits from every number of the array, and that can be accomplished by
i = number / digit.
For example, for the number 23456, I am supposed to start by extracting the number 2, which can be done by using
digit = 10000
and calculating
i = 23456 / 10000 = 2.
A recursive call is then supposed to look at the next digit, so in this case we want to get
i = 23456 / digit = 3
and so on. I know that there are certain methods for this, but how can this be done with using only primitves? I already tried to play around with modulo and dividing the digit, but it's not giving any desired result.
Basic Formula
The n-th digit of a non-negative, integral, decimal number can be extracted by the following formula:
digit = ((num % 10^n) / 10^(n-1))
where % represents modulo division, / represents integer division, and ^ represents exponentiation in this example. Note that for this formula, the number is indexed LSD->MSD starting from 1 (not 0).
This formula will also work for non-decimal numbers (e.g. base 16) by changing 10 to the desired base. It will also work for negative numbers provided that absolute value of the final digit is taken. Finally, it can even function to extract the integer digits (but not fractional digits) of a floating point number simply by truncating and casting the floating-point number to an integral number before passing it to this formula.
Recursive Algorithm
So, to recursively extract all of the digits of a number of a certain length in order MSD->LSD, you can use the following Java method:
static public void extractDigits(int num, int length) {
if (length <= 0) { // base case
return;
}
else { // recursive case
int digit = (num % (int)Math.pow(10,length)) / (int)Math.pow(10,length-1);
/* do something with digit here */
extractDigits(num, length-1); // recurse
}
}
This method will never divide by zero.
Note: In order to "do something with digit here," you may need to pass in an additional parameter (e.g. if you want to add the digit to a list).
Optimization
Since your goal is to extract every digit from a number, rather than only one specific digit (as the basic formula assumes), this algorithm may be optimized to extract digits in order LSD->MSD so as to avoid the need for exponentiation at each step. (this approach original given here by #AdityaK ...please upvote them if you use it)
static public void extractDigits(int num) {
if (num == 0) { // base case
return;
}
else { // recursive case
int digit = num % 10;
/* do something with digit here */
extractDigits(num / 10); // recurse
}
}
Note: Any negative number should be converted to a positive number before passing it to this method.
Here's the code to recursively extract numbers from an integer. It will be in reverse order.
import java.util.*;
public class HelloWorld{
static void extractNumbers(int n, List<Integer> l) {
if(n==0)
return;
else {
l.add(n%10);
extractNumbers(n/10, l);
}
}
public static void main(String []args){
List<Integer> result = new ArrayList<Integer>();
extractNumbers(456789,result);
System.out.println(result);
}
}
Hope it helps.
I would do something like this:-
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
int num=23456;
int numSize=5;
rec(num,numSize);
}
public static void rec(int num, int numSize){
if(numSize==0)
return;
int divideBy=(int)Math.pow(10,(numSize-1));
int out=(int)(num/divideBy);
System.out.println(out);
rec((num-out*divideBy),(numSize-1));
return;
}
See the output from here: http://ideone.com/GR3l5d
This can be easily done by using the for loop by converting the array elements into string.
var arr = [234, 3456, 1234, 45679, 100];
var compare = function(val1, val2) {
return val1 - val2;
};
arr.sort(compare); //sort function
var extract = function(value, index) {
var j = "";
var element = value + "";
for (var i in element) {
var val = element[i];
console.log(parseInt(val)); // this prints the single digits from each array elements
j = j + " " + val;
}
alert(j);
};
arr.forEach(extract); //extract function..

Function giving incorrect result

I know something is wrong with my variables storing the info.
At the end of the program, it prints 0.0 for rate.
I have been trying to figure out the error in logic or syntax in my program. I believe it may have something to do with the variables being 0, I have also tried inserting the function into the loop when count == floor.
import javax.swing.*;
public class pickanumber {
public static void main(String[] args) {
int floor=1, rooms, occupants, rsum = 0, osum = 0;
String amount;
do {
amount = JOptionPane.showInputDialog("Enter total floors.");
floor = Integer.parseInt(amount);
} while (floor <= 0);
for (int count = 1; count <= floor; count++) {
if (floor==13) count++;
do {
amount = JOptionPane.showInputDialog("Enter total rooms on floor "+count+".");
rooms = Integer.parseInt(amount);
} while(rooms <= 9);
rsum += rooms;
do {
amount = JOptionPane.showInputDialog("Enter occupants on floor "+count+".");
occupants = Integer.parseInt(amount);
} while ((occupants > rooms)||(occupants < 0));
osum += occupants;
}
int rate = (osum/rsum)*100;
JOptionPane.showInputDialog("occupancy is at "+rate+"% capacity.");
}
}
osumand rsum are both integers, they represent numbers without decimal.
Any math opertion using only those 2 integers will return an integer.
So osum/rsum will return
0 if osum < rsum
1 if rsum <= osum < 2*rsum
etc.
If you want to get the decimal value of this division, you can
define your rate as double type in order to contain decimal numbers.
cast at least one of your varaible as a double in the operation
You should end with something like:
double rate = (((double) osum)/rsum)*100;
The problem lies within the datatypes i guess (or atleast i couldn't think of anything else). the result of (osum/rsum) must be integer, and will therefor nearly always be 0 (or 1, if osum == rsum). Simply cast them to double before the division, and cast the result of the complete calculation back to integer, and things should work quite fine.
Double drsum = (double) rsum;
Double dosum = (double) osum;
Double rate = (dosum/drsum)*100;
int i = rate.intValue();

Converting from int to double in java

the following code calculates change dispensed by a vending machine. My problem? I cant get the change variable to work as the compiler wont let me due to two different data types (int & double conversion). Can anyone please help me solve this problem.
I have tried casting "change" but then it wont print right amount.
For example, if the change is 0.25 cents, change value remains zero..for obvious reasons of course. The problem begins at line 16. I have commented the part giving example as change = 0.25.
public String[] itemList = new String[] {"Water ","Coke ", "Diet Coke", "Iced Tea","Fanta "};
public double[] priceList = new double[] {75,120, 120, 100, 150};
public int[] itemQty = new int[]{10,10,10,10,10};
public int[] coinList = new int[]{100,50,20,10,5};
public int[] coinQty = new int[]{10,10,10,10,10};
public double change;
public double paid;
public void ReturnChange()
{
int Denominations=5;
int coins_dispensed = 0 ;
int[] InitialArray = new int[Denominations];
//My Problem begins here..for example if change is computed
change = 0.25; //change is a global declaration of type double and carries values derived from different function
int change1 = (int)change; //if i cast here, i get change as 0, thus the part that follows, fails to compute coins dispensed.
for (int i=0; i < 5; i++)
{
InitialArray[i] += coinQty[i]; // Copies Coin Quantity to Initial array for difference
}
System.out.println("Your change is "+NumberFormat.getCurrencyInstance().format(Math.abs(change1)) +" which comprises of:"); //OK till here
for (int i=0; i<5; i++)
{
if (coinQty[i]>0) //if a particular denomination is available
{
coins_dispensed = (change1/coinList[i]); //dividing coins dispense with denomination
coinQty[i] -= coins_dispensed; //reduce the quantity of the denomination dispensed
change1 = change1 - (coinList[i] * coins_dispensed); //total the change
}
else // Moves to next denomination if a particular coin runs out
{
coins_dispensed = (change1/coinList[i+1]);
coinQty[i+1] -= coins_dispensed ;
change1 = change1 - (coinList[i+1] * coins_dispensed);
}
}
if (change1 != 0) // In the case not enough coins to make change, selection is ignored.
{
System.out.println("\n\n\t Sorry. The machine doesnt have enough coins to make up your change. Your last transaction has been ignored.");
}
else
{
for (int i=0; i<Denominations; i++)
{
coins_dispensed = InitialArray[i] - coinQty[i];
System.out.println( "\n\t\t\t" + coins_dispensed +" of "+ coinList[i] + " cents coins");
}
}
}
You should use use integers everywhere but count in cents not dollars. Just divide your numbers by 100 when you print them.
This is because floats and doubles cannot accurately represent the base 10 multiples used for money and will introduce rounding errors, particularly when multiplying to calculate interest rates for example.
See Why not use Double or Float to represent currency? for more information and discussion.
It seems all your variables hold prices in cents (i guess a coke is not 120 $). But your change is apparently specified in dollars. So what you could do is multiply change by 100 and then cast it to int.
Like that:
int change1 = (int) (change * 100); // convert dollars to cents and cast to int
If you need to output change1 in dollars (and not cents) at some point, you have to convert it back:
float result = change1 / 100.0f;

Categories

Resources