Java Rounding two digits after decimal point without Math.round, BigDecimal, etc - java

Hay,
I want to round a number two digits after the decimal point only by using this mathematic formula:
For example the number 831.38849 should be rounded to 831.39 and printed out. I have tried something like this, but it didn't work: 0.01 * (100 * number + 0.5)
I know that similar questions have been asked before, but I'm not allowed to use all the fancy and easy stuff for this task like Math.round, BigDecimal, etc

⌊ ⌋ are math symbols for the floor function1, 2, 3
So the correct implementation of the mathematic formula
is the following Java code:
Math.floor(100d * number + 0.5) / 100d
Note: 100d can also be written 100.0, 100., or simply 100 (assuming number is a double)

So, the fancy part is handled by casting your floating point number to an integral value. You want to eliminate the portion two places to the right of the decimal, so you first multiply it by 100 to shift the decimal, add the 0.5 to round up anything 0.5 or higher, cast to an int (or a long) to truncate it, then divide by 100 to shift the decimal point back.
[Edit -- Adding condition to handle negatives, so it meets definition of "floor".]
double original_number = 831.38849;
double rounded_number = (original_number >= 0)
? ((long) (original_number * 100 + 0.5)) / 100.0
: ((long) (original_number * 100 - 0.5)) / 100.0;

Related

Math.pow restricting the calculation to one decimal point

I am trying to do following calculation in my java class
Math.pow (0.0901 / 12 * (1 + 0.0901 / 12), 356.966667)
I am getting 0.0 as the result. However the expected result is 0.10844
I am not so sure that your result should be 0.10844. The base number is something like this ~0.00756 and you raise it to a positive power of ~357. This means that for such a big power, you will have many more zeroes after the decimal point. This means you will have a positive value smaller that the one double can store and it will be rounded to 0.0.
Using BigDecimal you will get the following value: ~7.08E-756 for your computation while the smallest positive double value (Double.MIN_VALUE) is 4.9E-324. This means that 0.0 will be your rounded value.

Retrieve number after point in BigDecimal number without RoundingMode

how to keep only 3 value after point in BigDecimal ?
i found a solution but it requirt a RoundingMode
BigDecimal d = BigDecimal.valueOf(0.5649);
System.out.println(d.remainder(BigDecimal.ONE));
System.out.println(d.remainder(BigDecimal.ONE).divide(BigDecimal.valueOf(1), 3, RoundingMode.CEILING));
i want to keep a number exact without rounding.
Just use setScale and RoundingMode.DOWN
Rounding mode to round towards zero. Never increments the digit prior
to a discarded fraction (i.e., truncates).
for example
BigDecimal.valueOf(0.5649).setScale(3, RoundingMode.DOWN)
BigDecimal isn't intended to be used with such limitations. Only ever wanting 3 decimals is a strange requirement. Maybe you only want to present 3 decimals to the users?
If so I suggest using: java.text.DecimalFormat
If you really want to make sure that you never do calculations with higher precission than 3 decimals I suggest making your own reprensentation/class. Internally you hold the value as a long (or appropriate class/primitive) but at a value 1000 times the actual value. All calculations are done with the internal reprensentation and when asked for a value, divide the internal value with 1000.0d and convert to double (or appropriate) and return.
I would use double for this.
double d = 0.5649;
d = (long) (d * 1000) / 1000.0; // round down.
System.out.println(d);
prints
0.564
or
d = (long) (d * 1000 + 0.5) / 1000.0; // round half up.

Java: Trying to get the percentage of integers, how to round up?

I have two integer values, x and total. I am trying to find the percentage of x in total as an integer. This is how I am doing it right now:
percentage = (int)((x*100)/total);
The percentage must be an integer. When I do this it always rounds the decimal point down. Is there a simple way to calculate the percentage as an integer so it rounds up if the decimal is .5 or higher?
Use Math.round(x * 100.0/total). But note that this returns a long, so a simple cast to int will be required.
I put 100.0 to force it to use floating point arithmetic prior to the rounding.
(int)Math.round(100.0 / total * x);
should work.
Just use Math.round(100.0 / total * x);
Why not use Math.round((x*100)/total);
Use the standard math library in Java.
percentage = Math.round(*your expression here*);
You can add 0.5 for positive values (round to infitity)
percentage = (int)(x * 100.0 / total + 0.5);
This is faster than using Math.round, but possibly not as clear.
BTW: 100.0 / total * x might not give the same result as x * 100.0 / total as the order of evaluation can change the result for floating point.
Simplest Method -
Question : How to round up value of a decimal number(eg : int n = 4.57)
Answer : Math.round(n);
Output : 5 .

java - remove float leftovers elegantly

In brief - I am having a hard time with the float left overs
(i.e. 10.00000123 instead of 10)
Here I go :
I need to generate list of floats with constant gap as follows
(actually its a map , I need to retreive the object nut nevermind that)
List A: 0.25, 0.5, 0.75, 1, ...
or
List B: 0.01, 0.02, 0.03, 0.04, ...
every time I get a number and I round it to the neerest cell in the list.
lets say I get 0.051 to retreive a cell in list A - I return 0.05.
lets say I get 0.21 to retreive a cell in list B - I return 0.25.
So I started be doing this
float a = Math.round(Value / step) * step;
but than I get a lot of time 0.2500001 (float leftovers )
I need a smart way to round it .
Maybe by taking the number of digits after the dot and doing again
Math.round(Value / 100) * 100;?
Is there a smarter way?
I tried doig this
final float factor = Math.round(1 / step);
final float value = (float) Math.round(value * factor) / factor;
but I sometimes have a list like this
List A: 10, 15 , 20, 25, 30, ...
and when I get 22 I retreive the cell of 20.
the problem is that When I get a gap of 10
Math.round(1 / baseAssetStep)
returns 0 - and I get NaN
Use BigDecimal instead of float.
From the Java Tutorials of Primitive Data Types:
float: [...] This data type should never be used for precise values, such as currency. For that, you will need to use the
java.math.BigDecimal class instead. Numbers and Strings covers
BigDecimal and other useful classes provided by the Java platform.
Firstly, I would use double or long instead as these have much more digits of accuracy. If you really need to, use BigDecimal, but its pretty rare to find a real world situation where double or long would not do the job.
double d = 10.00000123;
double r = Math.round(d * 10000) / 10000.0;
or using long with fixed point precision.
long l = 100000; // the actual value * 10000
A common use case for fixed point precision is money. Instead of using dollars with double use cents with long or even int instead.
In short, "these are not the numbers you're looking for."
Floating points are represented as binary fractional numbers, and some numbers that can be easily represented in base-10 (0.01, for instance) can't be represented with a finite number of binary digits. This is similar to how 1/3 is easy in base 3 (it's just 0.1), but requires an infinite number of digits in base 10 (0.333...).
If you tried to represent 1/3 with a finite number of digits in base 10, you'd get an approximation. Similarly, if you try to represent 1/10 with a finite number of digits in base 2 (which is what float and double do), you'll get an approximation, and similarly with 1/100. What you think is 0.01 in the code is actually a number that's very close, but not exactly equal to, 1/100.
There are many resources out there concerning floating points and the difficulty in working with them. http://floating-point-gui.de/ is a good place to start.
you need a constant gap, so maybe try another solution. Take your gap, let's name it G. Draw a randow int - let's call it R, (if you know maximum number in your list you can draw it properly). Now the only thing to do would be R*G which will give you a number from your list - of course with some precision because this is inevitable using float - to print it just use format. You can also combine this with BigDecimal ;)

Java Double value = 0.01 changes to 0.009999999999999787 [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why not use Double or Float to represent currency?
I'm writing a basic command-line program in Java for my high school course. We're only working with variables right now. It's used to calculate the amount of bills and coins of whatever type in your change after a purchase. This is my program:
class Assign2c {
public static void main(String[] args) {
double cost = 10.990;
int paid = 20;
double change = paid - cost;
int five, toonie, loonies, quarter, dime, nickel, penny;
five = (int)(change / 5.0);
change -= five * 5.0;
toonie = (int)(change / 2.0);
change -= toonie * 2.0;
loonies = (int)change;
change -= loonies;
quarter = (int)(change / 0.25);
change -= quarter * 0.25;
dime = (int)(change / 0.1);
change -= dime * 0.1;
nickel = (int)(change / 0.05);
change -= nickel * 0.05;
penny = (int)(change * 100);
change -= penny * 0.01;
System.out.println("$5 :" + five);
System.out.println("$2 :" + toonie);
System.out.println("$1 :" + loonies);
System.out.println("$0.25:" + quarter);
System.out.println("$0.10:" + dime);
System.out.println("$0.05:" + nickel);
System.out.println("$0.01:" + penny);
}
}
It should all work but at the last step when there's $0.01 leftover, number of pennies should be 1 but instead, it's 0. After a few minutes of stepping into the code and outputting the change value to the console, I've found out that at the last step when change = 0.01, it changes to 0.009999999999999787. Why is this happening?
Using double for currency is a bad idea, Why not use Double or Float to represent currency?. I recommend using BigDecimal or doing every calculation in cents.
0.01 does not have an exact representation in floating-point (and neither do 0.1 nor 0.2, for that matter).
You should probably do all your maths with integer types, representing the number of pennies.
doubles aren't kept in decimal internally, but in binary. Their storage format is equivalent to something like "100101 multiplied by 10000" (I'm simplifying, but that's the basic idea). Unfortunately, there's no combination of these binary values that works out to exactly decimal 0.01, which is what the other answers mean when they say that floating point numbers aren't 100% accurate, or that 0.01 doesn't have an exact representation in floating point.
There are various ways of dealing with this problem, some more complicated than others. The best solution in your case is probably to use ints everywhere and keep the values in cents.
As the others already said, do not use doubles for financial calculations.
This paper http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html (What Every Computer Scientist Should Know About Floating-Point Arithmetic) is a must-read to understand floating point math in computers.
Floating point numbers are never 100% accurate (not quite true, see comments below). You should never compare them directly. Also integer rounding. The best way to do this would probably be to do it in cents and convert to dollars later (1 dollar == 100 cents). By converting to an integer you are losing precision.
its a float(double)
You should not use it to compute money....
I recommend using int values and operate on pennys
This is a problem that's arisen many times over. The bottom line is that on a computer that uses binary floating point (which Java requires), only fractions in which the denominator is a power of 2 can be represented precisely.
The same problem arises in decimal. 1/3, for example, turns into 0.3333333..., because 3 isn't a factor of 10 (the base we're using in decimal). Likewise 1/17, 1/19, etc.
In binary floating point, the same basic problem arises. The main difference is that in decimal, since 5 is a factor of 10, 1/5 can be represented precisely (and so can multiples of 1/5). Since 5 is not a factor of 2, 1/5 cannot be represented precisely in binary floating point.
Contrary to popular belief, however, some fractions can be represented precisely -- specifically those fractions whose denominators with only 2 as a prime factor (e.g., 1/8 or 1/256 can be represented precisely).
I'm sure you know that some fractions' decimal representations terminate (e.g. .01) while some don't (e.g. 2/3=.66666...). The thing is that which fractions terminate changes depending on what base you're in; in particular, .01 doesn't terminate in binary, so even though double provides a lot of precision it can't represent .01 exactly. As others said, using BigDecimal or fixed-point integer computations (converting everything to cents) is probably best for currency; to learn more about floating point, you could start at The Floating-Point Guide- What Every Programmer Should Know About Floating-Point Arithmetic.

Categories

Resources