So I need to change doubles such as 143.203030 to 143.20 rounding the second digit up or down(like money) my plan was to turn the double into an array and then if the third number after the decimal is 5 or greater the previous element would be one greater than it was. How do i access each int of a double and how would i turn my array of int back into doubles. Now... This is obviously a terrible and inefficent way, what would be a better idea. I would take the time to code that but I figured explaining it and asking for a better way is the same thing. Well actually i couldn't code that because I dont know to access each part of a double.
Try this:
public static roundHundredth(double d) {
return (double)((int)(d*100)+.5)/100;
}
A better idea, especially if you are working with money, is to use the BigDecimal class. It supports a variety of rounding modes meeting most common financial and engineering requirements.
To meet your immediate needs, you can use BigDecimal as follows (although it may be best to eliminate the double type from your program and use BigDecimal throughout):
String[] round(double[] arr) {
String[] r = new String[arr.length];
for (int idx = 0; idx < arr.length; ++idx) {
r[idx] = BigDecimal.valueOf(arr[idx]).setScale(2, RoundingMode.HALF_UP).toString();
}
}
I agree that you shouldn't use a double to store a money value (although will probably work OK for smaller amounts). The general approach for doing this kind of rounding is
double rounded = Math.round(d * 100) / 100.0;
Related
I have a program which multiplies a probability over 500 times, but when I am doing so the output is zero. Should I use some other data type?
Please help.
Here is the code I am using:
double d = 1/80000d;
for (int i = 0; i < 500; i++) {
d *= d;
}
System.out.println(d);
The output is zero because double has a limited percision, and if you multiply a number lower than 1 by itself enough times, you'll get a result too small to be distinguished from 0.
If you print d after each iteration, you'll see that it becomes 0 quite fast :
1.5625E-10
2.4414062500000002E-20
5.960464477539064E-40
3.552713678800502E-79
1.2621774483536196E-157
1.593091911E-314
0.0
When working with probabilities, you can avoid these sort of numerical issues by working instead with logarithms, so that you can work additively. Something like
double d = 1/80000d;
double ld = Math.log(d)
for (int i = 0; i < 500; i++) {
ld += ld;
}
System.out.println(ld);
Naturally, if you have two numbers less than 1, and repeated the multiply times sooner or later will be small enough to not be able resepresented in Double, Extended, or any floating arithmetic it done in the future. ;)
What your turn is the aproximation that has been stored in the type. ZERO is one of the special constants of IEEE 754 format.
I do not know JAVA, but exist the type Extended in other languages.
The double Value increases randomly.
for(double i=-1;i<=1;i+=0.1)
{
for(double j=-1;j<=1;j+=0.1)
{
//logic
system.out.print(i);
system.out.print(j);
}
}
Here, the value comes like:
-1, -0.9, -0.8, -0.69, -0.51 ....-0.099 , 1.007 (WHY, U ARE GREATER THAN 1)
The output is not same but kind of this.
But, I want the exact values only. WHat should I do ??
You can use an integer counter, and multiply to get the double:
for(int i = -10; i <= 10; i++) {
double iDouble = 0.1 * i;
....
}
The double will still have rounding error - that is inevitable - but the rounding error will not affect the loop count.
You can't get exact values do to the limitations of doubles. They can't always represent exactly the decimal you want, and they have precision errors. In your case you may want to cast the double to an int for the double comparison, but as #alex said you shouldn't be doing this.
This is due to the way that doubles are stored in memory, they are only exact if the fractional part is a negative power of two, e.g. 0, 1/2, 1/4, etc. This is also why you should never use equality statements for doubles, but rather > and <. For exact calculations, you could use BigDecimal:
BigDecimal bigDecimal = new BigDecimal(123.45);
bigDecimal = bigDecimal.add(new BigDecimal(123.45));
System.out.println(bigDecimal.floatValue()); // prints 246.9
As said here, floating-point variables must not be used as loop counters. Limited-precision IEEE 754 floating-point types cannot represent:
all simple fractions exactly
all decimals precisely, even when the decimals can be represented in a small number of digits.
all digits of large values, meaning that incrementing a large floating-point value might not change that value within the available precision.
(...) Using floating-point loop counters can lead to unexpected behavior.
Instead, use integer loop counter and increment another variable inside this loop like this:
for (int count = 1; count <= 20; count += 1) {
double x = -1 + count * 0.1;
/* ... */
}
I currently have a function which will take an input and round it to 4 decimal places, it looks like this:
public static double table_round(double n) {
return (double) Math.round(n * 10000) / 10000;
}
really really simple function, however I was thinking I could change it to allow a second variable to be passed that says how many places to round to, however I'm not sure exactly how to go about printing the correct number of 0's in the math statement there (each 0 represents one decimal place that will be printed). Any ideas on how this could be accomplished? This is just some extra credit stuff for my java class, I'm still learning so I'm sorry if there is a simple solution I'm overlooking.
public static double table_round(double n, int digits) {
return BigDecimal.valueOf(n).setScale(digits,BigDecimal.ROUND_HALF_UP).doubleValue();
}
You can use BigDecimal and its setScale() method to fix no of digits after decimal
public static double table_round(double n) {
// No of digits you want after decimal.
int digitsAfterDecimal = 5;
BigDecimal bigDecimal = BigDecimal.valueOf(n);
// BigDecimal.ROUND_FLOOR is Rounding Mode..denote how your value is rounded off
// Other ways are:- "ROUND_CEILING", "ROUND_DOWN", etc..
bigDecimal = bigDecimal.setScale(digitsAfterDecimal, BigDecimal.ROUND_FLOOR);
return Double.valueOf(bigDecimal.toString());
}
For detailed information, see http://www.opentaps.org/docs/index.php/How_to_Use_Java_BigDecimal:_A_Tutorial
For a small project (Problem 10 Project Euler) i tried to sum up all prime numbers below 2 millions. So I used a brute force method and iterated from 0 to 2'000'000 and checked if the number is a prime. If it is I added it to the sum:
private int sum = 0;
private void calculate() {
for (int i = 0; i < 2000000; i++) {
if (i.isPrime()) {
sum = sum + i;
}
}
sysout(sum)
}
The result of this calculation is 1179908154, but this is incorrect. So i changed int to BigInteger and now i get the correct sum 142913828922. Obviously the range of int was overflowed. But why can't Java tell me that? (e.g. by an exception)
Because it's conceivable that you might want it to behave in the traditional Integer fashion. Exceptions are reserved for things that are definitely and irrevocably wrong.
ETA: From the language spec:
"The built-in integer operators do not
indicate overflow or underflow in any
way. The only numeric operators that
can throw an exception (§11) are the
integer divide operator / (§15.17.2)
and the integer remainder operator %
(§15.17.3), which throw an
ArithmeticException if the right-hand
operand is zero."
(http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html)
Besides what Jim says, checking for conditions such as overflow would add a performance penalty to any calculation done with integers, which would make programs that do a lot of calculations a lot slower.
The other reason is that you can do this check yourself very easily and quickly.
if (sum+i < sum) {
throw new AritchmeticException();
}
should do the trick nicely, given that you know i is always positive and less than Integer.MAX_VALUE.
Being aware of Integer.MAX_VALUE is always useful :)
Because our profession values performance over correctness. ;(
Using BigInteger by default, and only reasoning whether it is acceptable, to use long or int if performance is a real problem, would help to avoid such problems.
I am working on an exercise in Java. I am supposed to use / and % to extract digits from a number. The number would be something like 1349.9431. The output would be something like:
1349.9431
1349.943
1349.94
1349.9
I know this is a strange way to do but the lab exercise requires it.
Let's think about what you know. Let say you have the number 12345. What's the result of dividing 12345 by 10? What's the result of taking 12345 mod 10?
Now think about 0.12345. What's the result of multiplying that by 10? What's the result of that mod 10?
The key is in those answers.
if x is your number you should be able to do something like x - x%0.1 to get the 1349.9, then x - x%.0.01 to get 1349.94 and so on. I'm not sure though, doing mod on floats is kind of unusual to begin with, but I think it should work that way.
x - x%10 would definetly get you 1340 and x - x%100 = 1300 for sure.
Well the work will be done in background anyway, so why even bother, just print it.
float dv = 1349.9431f;
System.out.printf("%8.3f %8.2f %8.1f", dv, dv, dv);
Alternatively this could be archived with:
float dv = 1349.9431f;
System.out.println(String.format("%8.3f %8.2f %8.1f", dv, dv, dv));
This is a homework question so doing something the way you would actually do in the real world (i.e. using the format method of String as Margus did) isn't allowed. I can see three constraints on any answer given what is contained in your question (if these aren't actually constraints you need to reword your question!)
Must accept a float as an input (and, if possible, use floats exclusively)
Must use the remainder (%) and division (/) operator
Input float must be able to have four digits before and after the decimal point and still give the correct answer.
Constraint 1. is a total pain because you're going to hit your head on floating point precision quite easily if you have to use a number with four digits before and after the decimal point.
float inputNumber = 1234.5678f;
System.out.println(inputNumber % 0.1);
prints "0.06774902343743147"
casting the input float to a double casuses more headaches:
float one = 1234.5678f;
double two = (double) one;
prints "1234.5677490234375" (note: rounding off the answer will get you 1234.5677, which != 1234.5678)
To be honest, this had me really stumped, I spent way too much time trying to figure out how to get around the precision issue. I couldn't find a way to make this program work for 1234.5678f, but it does work for the asker's value of 1349.9431f.
float input = 1349.9431f;
float inputCopy = input;
int numberOfDecimalPoints = 0;
while(inputCopy != (int) inputCopy)
{
inputCopy = inputCopy * 10;
numberOfDecimalPoints++;
}
double inputDouble = (double) input;
double test = inputDouble * Math.pow(10, numberOfDecimalPoints);
long inputLong = Math.round(test);
System.out.println(input);
for(int divisor = 10; divisor < Math.pow(10, numberOfDecimalPoints); divisor = divisor * 10)
{
long printMe = inputLong - (inputLong % divisor);
System.out.println(printMe / Math.pow(10, numberOfDecimalPoints));
}
Of my three constraints, I've satisfied 1 (kind of), 2 but not 3 as it is highly value-dependent.
I'm very interested to see what other SO people can come up with. If the asker has parsed the instructions correctly, it's a very poor exercise, IMO.