Java dividing two floats/doubles (values retrieved from variables) - java

I have a weird division problem with floats and doubles. I want to do a variety of divisions and multiplications.
See the following code:
List<Double> values = List.of(25.0, 25.0);
System.out.println(values);
// prints: [25.0, 25.0]
float totalValue = 0f;
for (Double value : values) {
totalValue = totalValue + value.floatValue();
}
float numValues = (float) values.size();
float completeValue = totalValue / numValues;
// completeValue: 6.25, totalValue: 50.0, numValues: 2.0
float rndValue = 50f / 2f;
// rndValue: 25.0
String oneDpValue = String.format("%.1f", completeValue);
return Double.valueOf(oneDpValue);
I'm confused as to why completeValue comes back completely wrong. I've added rndValue just for comparison when values aren't taken from variables and it returns the correct result.
Note:
Values in the comments are produced by a debugger in IntelliJ. I've also attempted at simply printing totalValue and numValues. Both come back as 50.0 and 2.0, respectively.
Could someone kindly explain why this is?
I have looked around for similar problems and tried using a suggestion (for a somewhat similar problem) to use BigDecimal, however, it still produced the same result.
Thanks!

First of all, thank you all for your input.
It turns out the completeValue was cached (even though I did reset the cache and restart my IDE). It simply took re-writing the same line and the correct result was being produced.
float completeValue = totalValue.floatValue() / numValues; // completeValue: 6.25;
float completeNewValue = totalValue.floatValue() / numValues; // completeNewvalue: 25.0
I must say I've never seen this happen in the past, however I hope it helps someone who has a similar issue in the future.

Related

Remove tailing ".0" from prices

How I can remove ".0" from my Price number from my android studio app?
MyApp save orders in database, then user can place order, after that server app get the orders placed.
I'm also using Retrofit2.
I have double prices 2000.0.
I want them without tailing 0, just 2000.
There are other sections with this problem, which I guess some guide about how to fix this part can help me to fix other parts.
There are 2 ways you can solve this.
(Adding to Andreas comment)
Either use int instead of double altogether.
Or you can always cast your double value in int.
double x = 1000.324;
System.out.println("double x = "+x);
System.out.println("int x = "+(int) x);
prints:
double x = 1000.324
int x = 1000
You could use :
new DecimalFormat("#").format(2000.0);
The result is "2000" without decimals.
There are a few things you can do do remove the numbers after the decimal and it depends on what you are trying to achieve.
You can cast them to an Int or use new DecimalFormat("#").format(value) which will remove anything after the .
You can use the Math.rint() or Math.round functions this will round to the closest integer 3.99 will become 4
Simply typecast your double value into int
double percentageValue=200.0;
System.out.println("remove value of after decimal point=="+(int)percentageValue);
and set value in android just like this:-
txt_product_price.setText(String.valueOf((int)percentageValue));
simply convert the Double value to Integer
Double x = 2000.0;
Integer y = (int) x;
Log.e("Integer format",String.valueOf(y));
and the Log is 2000

Java - using int values to calculate average (a decimal value) using proper casting methods

So this is a basic question, I have 2 int variables or field as it is called in Java. One is total score the other is game rounds. I am using double which takes decimal numbers as the data type for average variable. But I'm not getting the correct result.
int totalScore = 75;
int gameRounds = 2;
public void calculateAverage() {
double average = totalScore / gameRounds;
System.out.println(average);
}
The result is: 37.0, why isn't it the result 37.5, even though I'm using the correct datatype?
So I figured it out! I tried casting the value to double, it works perfectly now. The result is 37.5. But I would like to get other answers if they have better solution to this.
double average = (double)totalScore / gameRounds;
NOTE: When I used brackets around the int values it didn't work
as shown below. So make sure to do as I showed above.
double average = (double)(totalScore / gameRounds);

replacing float to double via whole project

I have a legacy project and it has math that uses float and long variables like this:
long i = initWihtVeryBigNumber();
float multiplier = 1.3f;
i *= multiplier;
this basically cause round error due to float size and this has to be replaced with:
i = (long)( i* (double)multiplier );
or multiplier itself should be double instead of float.
So the question if I change through entire project float to double could this cause any unpredictable behavior or not ? If so can you provide any example that can produce a problem ?
So the question if I change through entire project float to double could this cause any unpredictable behavior or not ? If so can you provide any example that can produce a problem ?
Yes. Changing (float) to (double) could cause issues, whenever the method requires a float. For example,
Float.toString((double) 1.0f);
Is a compilation error.
Edit
I'm interested in run-time errors rather then in compilation errors.
Okay. You have a third party library that returns a List<Float> (so testIt() below is from a third party). If you blindly cast elements from that List to Float you will get a run-time error.
public static List<Float> testIt() {
List<Float> al = new ArrayList<Float>();
al.add(1.0f);
return al;
}
public static void main(String[] args) {
List<?> al = testIt();
for (int i = 0; i < al.size(); i++) {
Object o = al.get(i);
Double v = (Double) o;
System.out.println(v);
}
}
Another difference is that unlike float, writes to non-volatile double fields aren't guaranteed to be atomic.
It is an unlikely scenario that only affects multi-threaded systems that haven't been synchronized correctly but boy does it cause unexpected runtime problems.
Note that you're still going to get rounding errors even if you change floats to doubles. Example: suppose we set i to 3703816849309525656 (= 3 * 0x1122334455667788, just a number I tried as an experiment).
long i = 3703816849309525656L;
float multiplier = 1.3f;
i *= multiplier;
System.out.println(i);
outputs
4814961529147359232
long i = 3703816849309525656L;
double multiplier = 1.3;
i *= multiplier;
System.out.println(i);
outputs
4814961904102383616
But using a calculator program (GNU bc):
(3703816849309525656 * 13) / 10
4814961904102383352.8
So using a double gets you a lot closer, but the result is still incorrect; and when one deals with integers, one normally expects exact results. Therefore, I'd consider using BigInteger or BigDecimal, although I realize that change would require a lot more effort.

Java / Android - equation for rounding up

I am building an android application. In my app, i need to be able to round up a double (42.42 for example) and also get how much i added to the original number in order to round it up. My current code isn't working, and its outputting 0.. Anyway to fix this?
My current code:
float rounded = FloatMath.ceil(val);
double getDecimal = (val - FloatMath.floor(val))*100;
int noDecimal = (int) ((int) 100-getDecimal);
float toadd = (noDecimal/100);
In my code the "rounded" variable is the simpel rounding, and "toadd" should be how much i added to it. For some reason toadd always comes back as 0. Any help?
You're dividing noDecimal by 100. Both are ints, and the result will always be an int. In this case, it's an int between 0 and 1, which will always be truncated to 0.
What's wrong with just getting the number modulo 1 (%1), then getting the ceiling of the original number?
For completeness, you could simply change the last line to preserve the rest of the logic:
float toadd = noDecimal/100.0;
This changes the divisor to a float, and an int divided by a float yields a float.
float toadd = (noDecimal/100);
This will give you 0, as you are dividing smaller integer by larger one..
Try to do like this: -
float toadd = (Float.valueOf(noDecimal)/100);
Also, you don't need to do typecast twice in the below code: -
int noDecimal = (int) ((int) 100-getDecimal);
Just, outer cast is enough: -
int noDecimal = (int) (100-getDecimal);
Edit: - Also, you might want to use BigDecimal for this kind of problems..
Maybe I'm missing something or not getting your intention right, but if you just want to know what you added, why don't just use the difference?
float rounded = FloatMath.ceil(val);
float toadd = rounded-val;
Edit: As mentioned in the comments, this might not always give the absolutely accurate result. But it's the general idea which can be used with BigDecimal, which offers a higher precision.

Java using Mod floats

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.

Categories