So I'm a little frustrated with how many times I've tried this.
I'm using # / 100 = % * Balance = Fine here, yet for some reason always results to 0. Note that this uses an external API.
double fine = (getConfig().getBoolean("fineispercentage") == true ? getConfig().getInt("fine") / 100 * count * econ.getBalance(event.getPlayer().getName()) : econ.getBalance(event.getPlayer().getName()) - (econ.getBalance(event.getPlayer().getName()) - count * getConfig().getInt("fine")));
When true, always results to 0. When false, it goes the way it's supposed to, which is subtract an amount depending on the count.
Try this (not tested):
double fine = (getConfig().getBoolean("fineispercentage") == true ? getConfig().getInt("fine") / 100.0 * count * econ.getBalance(event.getPlayer().getName()) : econ.getBalance(event.getPlayer().getName()) - (econ.getBalance(event.getPlayer().getName()) - count * getConfig().getInt("fine")));
The trick is to divide by 100.0 (double), not 100 (int)
Assuming that getConfig().getInt() returns an int, this java division:
getConfig().getInt("fine) / 100
Will do an integer division, and produce an int result, which will truncate any decimal part, so any value of "fine" 0-99 will result in a zero. The fix is this:
getConfig().getInt("fine) / 100d
Adding the "d" to 100 makes the 100 a double value, which will perform a double division, keeping the decimal part.
Assuming getInt does actually return an integer, it looks like you're doing integer division, giving you 0.
Divide getConfig().getInt("fine") by 100d instead of 100:
double fine = (getConfig().getBoolean("fineispercentage") == true ? getConfig().getInt("fine") / 100.0 * count * econ.getBalance(event.getPlayer().getName()) : econ.getBalance(event.getPlayer().getName()) - (econ.getBalance(event.getPlayer().getName()) - count * getConfig().getInt("fine")));
Related
I'm implementing a business rule to calculate a percentage increase on a stock level:
Stock level | Percentage Increase | Expected output
100 | 93 | 193
As decimal stock levels are not well defined the rule is to round up the output:
public int calculateStockLevel(int rawStockLevel, double percentageIncrease) {
return Math.ceil(rawStockLevel * (1 + (percentageIncrease / 100));
}
Actual output for the situation above: 194 (The test fails)
This looks like a floating point precision error, whats an elegant & readable way to get this test to pass?
You should use BigDecimal to specify what precision you want, but for your case you could do something simpler: just divide by 100 at the end.
public int calculateStockLevel(int rawStockLevel, double percentageIncrease) {
return Math.ceil(rawStockLevel * (100 + percentageIncrease) / 100);
}
Binary floating-point types can't represent exactly every value in decimal. So percentageIncrease / 100 will get the closest representation in binary. In your case the exact value of 0.93 in double precision is 0.930000000000000048849813083507, which is slightly more than the true decimal value. Therefore after ceil it'll be rounded up to 0.94
If you want exact decimal output you must use decimal arithmetic, like BigDecimal. But in your case you can just do it in plain integer, utilizing the fact that the fractional part of the result must be larger than 0 if remainder of the division is non-zero.
int temp = rawStockLevel * (100 + percentageIncrease);
int result = temp/100;
if (temp % 100 != 0)
result++; // round up if not divisible by 100
return result;
While working on one implementation, i saw difference in amount being shown at 2 places.While doing some more debugging i found this information.
I have 2 decimal values and both getting rounded to 2 decimal places.
double value =1091.225;
double value1 =48.125;
System.out.println((double)Math.round(value * 100) / 100);
System.out.println((double)Math.round(value1 * 100) / 100);
BigDecimal price = new BigDecimal(value);
price = price.setScale(2, RoundingMode.UP);
double val= ((long) (value < 0 ? value * 100 - 0.5 : value * 100 + 0.5)) / 100.0;
BigDecimal price1 = new BigDecimal(value1);
price1 = price1.setScale(2, RoundingMode.UP);
double val1= ((long) (value1 < 0 ? value1 * 100 - 0.5 : value1 * 100 + 0.5)) / 100.0;
System.out.println(val);
System.out.println(val1);
These are results
1091.22
48.13
1091.22
48.13
However if i change values to
double value =1091.255;
double value1 =48.125;
Results are different
1091.26
48.13
1091.26
48.13
Can anyone please help me to understand as why this is happening?
It's because of the way floating point numbers are stored in memory. The value 1091.225, and 1091.255d, don't have exact binary representation. Try printing their value using the below statements:
System.out.println(new BigDecimal(1091.225d));
System.out.println(new BigDecimal(1091.255d));
Output will be:
1091.22499999999990905052982270717620849609375
1091.2550000000001091393642127513885498046875
It's clear that the first one will be rounded to .22, and 2nd one to .26.
This is caused because decimal values are not stored as precise values, and you are discarting decimal part by casting to long.
Try this to better understand:
System.out.println(value * 100 + 0.5);
System.out.println((long)(value * 100 + 0.5));
This prints
109122.99999999999
109122
So divided by 100.0 it is 1091.22
But for other values it prints
109126.00000000001
109126
So divided by 100.0 it is 1091.26
Math.round() is the issue here.
public static int round(float a) Returns the closest int to the
argument. The result is rounded to an integer by adding 1/2, taking
the floor of the result, and casting the result to type int. In other
words, the result is equal to the value of the expression:
(int)Math.floor(a + 0.5f)
Hope this helps.
Also, note that the precision for decimal point values are not accurate, since they cannot be represented perfectly in binary form.
This should help.
I'd like to round manually without the round()-Method.
So I can tell my program that's my number, on this point i want you to round.
Let me give you some examples:
Input number: 144
Input rounding: 2
Output rounded number: 140
Input number: 123456
Input rounding: 3
Output rounded number: 123500
And as a litte addon maybe to round behind the comma:
Input number: 123.456
Input rounding: -1
Output rounded number: 123.460
I don't know how to start programming that...
Has anyone a clue how I can get started with that problem?
Thanks for helping me :)
I'd like to learn better programming, so i don't want to use the round and make my own one, so i can understand it a better way :)
A simple way to do it is:
Divide the number by a power of ten
Round it by any desired method
Multiply the result by the same power of ten in step 1
Let me show you an example:
You want to round the number 1234.567 to two decimal positions (the desired result is 1234.57).
x = 1234.567;
p = 2;
x = x * pow(10, p); // x = 123456.7
x = floor(x + 0.5); // x = floor(123456.7 + 0.5) = floor(123457.2) = 123457
x = x / pow(10,p); // x = 1234.57
return x;
Of course you can compact all these steps in one. I made it step-by-step to show you how it works. In a compact java form it would be something like:
public double roundItTheHardWay(double x, int p) {
return ((double) Math.floor(x * pow(10,p) + 0.5)) / pow(10,p);
}
As for the integer positions, you can easily check that this also works (with p < 0).
Hope this helps
if you need some advice how to start,
step by step write down calculations what you need to do to get from 144,2 --> 140
replace your math with java commands, that should be easy, but if you have problem, just look here and here
public static int round (int input, int places) {
int factor = (int)java.lang.Math.pow(10, places);
return (input / factor) * factor;
}
Basically, what this does is dividing the input by your factor, then multiplying again. When dividing integers in languages like Java, the remainder of the division is dropped from the results.
edit: the code was faulty, fixed it. Also, the java.lang.Math.pow is so that you get 10 to the n-th power, where n is the value of places. In the OP's example, the number of places to consider is upped by one.
Re-edit: as pointed out in the comments, the above will give you the floor, that is, the result of rounding down. If you don't want to always round down, you must also keep the modulus in another variable. Like this:
int mod = input % factor;
If you want to always get the ceiling, that is, rounding up, check whether mod is zero. If it is, leave it at that. Otherwise, add factor to the result.
int ceil = input + (mod == 0 ? 0 : factor);
If you want to round to nearest, then get the floor if mod is smaller than factor / 2, or the ceiling otherwise.
Divide (positive)/Multiply (negative) by the "input rounding" times 10 - 1 (144 / (10 * (2 - 1)). This will give you the same in this instance. Get the remainder of the last digit (4). Determine if it is greater than or equal to 5 (less than). Make it equal to 0 or add 10, depending on the previous answer. Multiply/Divide it back by the "input rounding" times 10 - 1. This should give you your value.
If this is for homework. The purpose is to teach you to think for yourself. I may have given you the answer, but you still need to write the code by yourself.
Next time, you should write your own code and ask what is wrong
For integers, one way would be to use a combination of the mod operator, which is the percent symbol %, and the divide operator. In your first example, you would compute 144 % 10, resulting in 4. And compute 144 / 10, which gives 14 (as an integer). You can compare the result of the mod operation to half of the denominator, to find out if you should round the 14 up to 15 or not (in this case not), and then multiply back by the denominator to get your answer.
In psuedo code, assuming n is the number to round, p is the power of 10 representing the position of the significant digits:
denom = power(10, p)
remainder = n % denom
dividend = n / denom
if (remainder < denom/2)
return dividend * denom
else
return (dividend + 1) * denom
I'm trying to round the users input but I can seem to get my double to round to an int. Basically, when I enter 4.4999 it wont round up to 5.
Any ideas?
Math.ceil() returns the ceiled value. It can't change the value of the variable it takes as argument, because Java passes arguments by value. So you need to do
hours = Math.ceil(hours);
The actual solution is to use double inside the ceil method.
Math.ceil(7 * 50 / 100) will return 3.0 even though the actual value resulting from 7*50/100 is 3.5. It is because since everything is int, the result of 350/100 itself will be 3.
If however, if you give Math.ceil(7 * 50 / 100D), the result would be 4.0.
So, the 4.999 in your question should be a double and not a result of an integer operation like 4999/1000.
Just make sure that whatever you give inside a the ceil is double and not an int.
Both function return the rounded (or ceiled) values, but don't change the variable passed as parameter.
Use eg. hours = Math.ceil(hours);.
Math.ciel returns a Double. Something like this should work (inside of your hours > 0 block):
cost += Math.ceil(hours) * hourlyRate;
You're not assigning the result of Math.ceil(hours) back to hours so it will never round.
int a = 15
int b = 2;
int x = (int) Math.ceil( a / b );
int y = (int) Math.ceil( (double) a / (double) b );
Results:
x: 7
y: 8
I'd like to round integers down to their nearest 1000 in Java.
So for example:
13,623 rounds to 13,000
18,999 rounds to 18,000
etc
Simply divide by 1000 to lose the digits that are not interesting to you, and multiply by 1000:
i = i/1000 * 1000
Or, you can also try:
i = i - (i % 1000)
You could divide the number by 1000, apply Math.floor, multiply by 1000 and cast back to integer.
int i = Math.floorDiv(-13623, 1000) * 1000
//i => -14000
The above code will always round down (towards negative infinity) assuming the divisor (1000 in the example) is positive.
The other answer (i = i/1000 * 1000) rounds down when i is positive, but up when i is negative.
-13623 / 1000 * 1000 == -13000
There is also a version of Math.floorDiv for longs which will work for very large numbers where the Math.floor method might fail due to the precision of double.
There are also Math.floorMod methods to go with the floorDivs which might allow you to shorten it a bit:
int i = -13623;
i -= Math.floorMod(i, 1000);
//i => -14000