Java Modulus Weird - java

I write code to test methods, display food and price:
import java.util.Scanner;
public class JavaTutorial5Class {
public static void main(String[] args)
{
greeting("Thunderdome");
prices("Fatburger", 7.50);
}
static void greeting(String restaurant)
{
System.out.println("Welcome to " + restaurant);
}
static void prices(String burger, double price){
System.out.print(burger + " is " + "$" + price);
//System.out.println(Math.ceil(price % 10));
if (Math.ceil(price % 10) == 8.0){
System.out.print("0");
}
}
}
Why is price % 10 == 8.0? And is this really what you have to do to get the tailing 0 on there?
EDIT: All this code is supposed to do is print "Fatburger is $7.50" the problem is that simply giving it the argument 7.50 converts it to 7.5.

In this code, the reason you are getting 8.0 is due to you using Math.ceil.
7.5 % 10 is 7.5, and Math.ceil(7.5) is 8.0.
However, and this is something that comes up extremely often and is a very common mistake for beginners... prices should almost never be stored as doubles. Double arithmetic is not always as precise as you would expect, mainly because of how doubles are actually stored. For example, consider this:
double sum = 0.0;
int n = 6;
for (int i = 0; i < n; i++) {
sum += 1.0 / n;
}
System.out.println(sum);
You would expect it to output 1.0, but it actually outputs 0.9999999999999999
The correct way to handle prices is with two ints: one for dollars, one for cents.

Try this instead:
static void prices(String burger, double price){
System.out.print(burger + " is $" + price);
if ((int)(price * 10) == price * 10)
System.out.print(0);
}
As you have it now, 7.5 % 10 simply returns 7.5 and the Math.ceil rounds this up to 8.0.

price % 10 is actually 7.5. Modulu is the remainder of division (or how many times a number can fit into another). For example, 22 % 10 is 2, since 10 can fit into 22 twice without going over. Taking the ceiling, which raises it to the nearest integer, raising 7.5 it to 8. Hence the if statement is resulting as true.

I think ultimately the solution he wants (to print a double in the form of currency) can be solved as so...
Add import
import java.text.NumberFormat;
and use this code
NumberFormat nf = NumberFormat.getCurrencyInstance();
System.out.print(burger + " is " + "$" + nf.format(price));
Forget all the modulo stuff (it is over complicating and incorrect way to achieve what you are asking for).
Also there is a slight rounding issue with doubles and if you need perfect precision (doubtful given the rest of your code), but typically the standard is to use 2 ints to store currency).

Use the following command to format your string correctly:
System.out.printf(%s is $%.2f, burger, price)
Reference this page for a tutorial on string formatting: http://www.homeandlearn.co.uk/java/java_formatted_strings.html
The %s will be replaced by the value of burger, formatted as a string.
The %.2f will be replaced by the value of price, formatted as a decimal number with exactly 2 places after the decimal point.

Related

Getting the decimal number of a double

I am working with a cos value which is represented in double. So my bounds are between -1.0 and 1.0, however for my work I am simply ignoring all negative variables.
Now I'd like to get the decimal number of this double number (sorry I couldn't find the literature term of this operation)
Basically with examples:
Assume that input is 0.12 then this could be written as 1.2 * 10^-1, what I am expecting to get is just the part where it is 10^-1
Another example is 0.00351, which can be written as 3.51 * 10^-3, so the expected result is 10^-3
I have developed this algorithm below but it's kind of quick and dirty. I was wondering whether is there any mathematical trick to avoid using a loop.
double result = 1;
while (input < 1.0) {
input *= 10.0;
result /= 10.0;
}
Also the above doesn't handle if input is 0.
I am using Java for coding if that helps.
It appears you are looking for the base 10 exponent of the number - use Math.log10 to do this
Math.log10(input)
e.g.
log10(100) = 2
log10(1e-5) = -5
etc.
You'll need to remember the base you've used (10 in this case)
public class Tester {
public static double lowbase(double v) {
return Math.pow(10, Math.floor(Math.log10(Math.abs(v))));
}
public static void main(String [] args){
System.out.println(lowbase(0.12));
System.out.println(lowbase(0.00351));
System.out.println(lowbase(0));
System.out.println(lowbase(-1));
}
}
Gives:
0.1
0.001
0.0
1.0
The abs is for handling the negative numbers, you may fiddle with that for a different take on negatives.
In case you are actually looking for strings such as "10^-2" (as you said that the expected result would be in this format).
public String getCientific(double input){
int exp;
exp = (int) java.lang.Math.floor(java.lang.Math.log10(input));
return "10^" + exp;
}

Why is it adding the variables wrong?

I'm using Java but, it's not adding the amount correctly. I'll give my parts of my code.
final double taxrate=.08;
Map<String,Integer> Priceproduct= new HashMap<String,Integer>();
Priceproduct.put("shoes",(int) 50.00);
Priceproduct.put("shirts",(int) 30.00);
Priceproduct.put("shorts",(int) 75.00);
Priceproduct.put("caps",(int) 15.00);
Priceproduct.put("jackets",(int) 100.00);
System.out.print("\n Enter the product: ");
String product=keyboard.nextLine();
System.out.print( "\n Enter the quantity of the product");
int quantity=keyboard.nextInt();
int cost= Priceproduct.get(product)*quantity;
int tax= (int) (cost*taxrate);
System.out.print("\n tax=" +cost*taxrate+"");
int TotalBill= cost+tax;
System.out.print("\nTotal="+cost+ + +tax+"");
When it adds the cost and tax (those two are correct) it's gets the completely wrong answer.
For example 3 shirts= 90, the tax equals 7.2, and the total becomes 907.
Do I need to use DecimalFormat or something else?
Change this:
System.out.print("\nTotal="+cost+ + +tax+"");
to this:
System.out.println();
System.out.print("Total=" + (cost + tax));
(The problem is that + is left-associative, so without parentheses around your addition, "a" + b + c means ("a" + b) + c, which does string-concatenation at both stages.)
When you perform an operation alongside a string Java will perform that operation as if the operands were strings.
In your System.out.println() calls you don't need to redo the calculations, just print out the variables "tax" and "totalBill". (This will solve the problem of printing '907')
You will only ever get integer values because you are using int type for everything. If you want to have decimals to indicate cents you should be using type double.

Adding 1/3 in java results in 1.0, while it shouldn't

Note: question still not answered thoroughly! This questions does not deal with the issue of truncation of floating point parts!!!
In Java I have this simple code:
double sum = 0.0;
for(int i = 1; i <= n; i++){
sum += 1.0/n
}
System.out.println("Sum should be: 1");
System.out.println("The result is: " + sum);
Where n can be any integer. For numbers like 7,9, the expected value for sum is to have difference in the last digits of sum, and the result is 0.999999999998 or something but the output when I use 3 is 1.0.
If you add 1/3 3 times, you would expect a number close to 1, but I get exactly 1.0.
Why?
This is because the division is made in integer.
1/n always gives 0 for n > 1.
Therefore, you always end up with sum = 0 + 1/1 + 0 + 0...
Try with 1.0 / n
If you add 1/3 3 times, you would expect a number close to 1, but I
get exactly 1.0.
Actually a normal person uncontaminated by programming experience would expect n * 1 / n to equal 1, but we're not normal here.
I can't reproduce your problem exactly, I get
groovy:000> def foo(n) {
groovy:001> sum = 0.0
groovy:002> for (int i = 0; i < n; i++) {
groovy:003> sum += 1.0 / n
groovy:004> }
groovy:005> sum
groovy:006> }
===> true
groovy:000> foo(3)
===> 0.9999999999
There may be 2 issues here, at least you will want to be aware of them.
One is that doubles are not exact, they cannot represent some values exactly, and you just have to expect stuff to be off by a little bit. Your goal isn't 100% accuracy, it's to keep the error within acceptable bounds. (Peter Lawrey has an interesting article on doubles that you might want to check out.) If that's not ok for you, you'll want to avoid doubles. For a lot of uses BigDecimal is good enough. If you want a library where the division problems in your question give accurate answers you might check out the answers to this question.
The other issue is that System.out.println doesn't tell you the exact value of a double, it fudges a bit. If you add a line like:
System.out.println(new java.math.BigDecimal(sum));
then you will get an accurate view of what the double contains.
I'm not sure whether this will help clarify things, because I'm not sure what you consider to be the problem.
Here is a test program that uses BigDecimal, as previously suggested, to display the values of the intermediate answers. At the final step, adding the third copy of 1.0/3 to the sum of two copies, the exact answer is half way between 1.0 and the next double lower than it. In that situation the round-to-even rounding rule picks 1.0.
Given that, I think it should round to 1.0, contradicting the question title.
Test program:
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
final double oneThirdD = 1.0/3;
final BigDecimal oneThirdBD = new BigDecimal(oneThirdD);
final double twoThirdsD = oneThirdD + oneThirdD;
final BigDecimal twoThirdsBD = new BigDecimal(twoThirdsD);
final BigDecimal exact = twoThirdsBD.add(oneThirdBD);
final double nextLowerD = Math.nextAfter(1.0, 0);
final BigDecimal nextLowerBD = new BigDecimal(nextLowerD);
System.out.println("1.0/3: "+oneThirdBD);
System.out.println("1.0/3+1.0/3: "+twoThirdsBD);
System.out.println("Exact sum: "+exact);
System.out.println("Rounding error rounding up to 1.0: "+BigDecimal.ONE.subtract(exact));
System.out.println("Largest double that is less than 1.0: "+nextLowerBD);
System.out.println("Rounding error rounding down to next lower double: "+exact.subtract(nextLowerBD));
}
}
Output:
1.0/3: 0.333333333333333314829616256247390992939472198486328125
1.0/3+1.0/3: 0.66666666666666662965923251249478198587894439697265625
Exact sum: 0.999999999999999944488848768742172978818416595458984375
Rounding error rounding up to 1.0: 5.5511151231257827021181583404541015625E-17
Largest double that is less than 1.0: 0.99999999999999988897769753748434595763683319091796875
Rounding error rounding down to next lower double: 5.5511151231257827021181583404541015625E-17
An int divided by an int will always produce another int. Now int has no place to store the fractional part of the number so it is discarded. Keep in mind that it is discarded not rounded.
Therefore 1 / 3 = 0.3333333, and the fractional part is discarded meaning that it becomes 0.
If you specify the number as a double (by including the decimal point, ex. 1. or 1.0) then the result will be a double (because java automatically converts an int to a double) and the fractional part will be preserved.
In your updated question, you are setting i to 1.0 but i is still an int. So that 1.0 is getting truncated to 1 and for further calculations, it is still an int. You need to change the type of i to double as well otherwise there will be no difference in the code.
Alternatively you can use sum += 1.0/n
This will have the effect of converting n to a double before performing the calculation

Set number of decimal places to 0 if float is an integer (java)?

I'm using a float to hold a score. The score can be an integer or decimal. By default, floats display as 0.0, 1.0, etc. If the number does not have a decimal, I need it to display as 0, 1, etc. If it does have a decimal, then I need to display the decimal. How might I do this?
String string;
float n = 3.0f;
if (n % 1 == 0) {
string = String.valueOf((int) n);
} else {
string = String.valueOf(n);
}
System.out.println("Score: " + string);
Warning: Untested code. ;)
Ok, I've tested it and fixed an error.
You could use:
NumberFormat.getInstance().format(score);
to display with decimal places when present.
To counter against rounding errors, score here could be represented using a BigDecimal.
Your best bet is to work out the smallest granularity of score and then use that with an appropriate multiplier.
For example, if the smallest increment is 0.01, use a multiplier of 100. And if your score % mulitplier = 0 then you know its a whole number.
That way you dont need to worry about rounding, or representation errors.

Convert fraction to decimal number

i'm doing some exercises in my Java book. I'm very new to programming. Therefore, notice (in the code) that i'm still on Chapter one. Now I already did everything, I just want a confirmation if this is legitimate so I can feel free to move on next.
If not, I would sincerely appreciate to not do my code for me; I want advice.
Here's the question written in the book,
"Write an application that prompts/reads the numerator and denominator of a fraction as integers, then prints the decimal equivalent of the fraction."
I'll illustrate this sentence with my code:
I did a revision here. Is this one OK?..
import java.util.*;
public class ExerciseEleven {
public static void main (String[] args) {
Scanner sc = new Scanner (System.in);
double fraction;
int fractionValue;
int decimal;
double value;
System.out.println("Enter Numerator: ");
int numerator = sc.nextInt();
System.out.println("Enter Denominator: ");
int denominator = sc.nextInt();
fraction = (double) numerator / denominator;
fractionValue = (int) (fraction * 10);
decimal = fractionValue % 10;
value = decimal * 0.1;
System.out.println(value);
}
}
It compiles and works fine.
Thank you.
It doesn't do what task says it should. You read doubles instead of integers, and the decimal equivalent is not what you print out. Decimal equivalent for 1/2 is 0.5. And you print 5.
Also, you can pay attention to your code style: variable names are usually written in lowerCamelCase, like that : simpleVariable.
Update
now it prints what you need. However you do it not in the very right way and your indentation can still be improved.
It's fine (I didn't read the assignment very well, did I? Kudos to Vladimir.) ...but some comments:
Usually you want to indent methods within the class.
Standard practice is to use initial caps (Numerator) only for types (e.g., classes, interfaces, enums). Variable, field, and method names should start with a lower-case letter. Now, you're free to ignore standard practice, but if you do people will have a lot of trouble reading your code. :-)
For rounding, you probably want to look at Math.round rather than truncating with a cast. But the assignment didn't say anything about rounding.
You might want to handle the case where denominator is zero.
So keeping those in mind:
import java.util.*;
public class ExcerciseEleven {
public static void main (String[] args) {
Scanner sc = new Scanner (System.in);
System.out.println("Enter Numerator: ");
int numerator = sc.nextInt();
System.out.println("Enter Denominator: ");
int denominator = sc.nextInt();
if (denominator == 0) {
System.out.println("Can't divide by zero");
}
else {
double fraction = (double)numerator / denominator;
System.out.println(fraction);
}
}
}
Hey I am doing some thinking about this and I have noticed something interesting after looking at this source and here is the Algorithm that I plan on implementing
First I will convert the number from the Metric using the
Javax.Measure family of functions and I will get a number like
0.3750
Then I will divide the number by ONE_SIXTEENTH which = 0.0625
ONE_SIXTEENTH = 0.0625
The answer 0.3750 / ONE_SIXTEENTH = 6;
So now I know there are 6 sixteenths of the inch
Next I check to see if 6 is divisible by 4, 6/4 = 1.5 ie not a whole number so the fraction is still regarded as 6/16th of an inch for now
Next I check to see if 6 is divisible by 2, 6/2 = 3
This is a whole number so we will use it to reconstitute the fraction
So now that we have divided 6 by 2 and gotten 3 the 16 needs to be divided by 2 and we end up with 8 so 6/16th of an inch becomes 3/8th of an inch.
PS Has anyone noticed that this is similar to a fizz bang program?
____________________________________________
Here is the chart which helped me get my head around this
My workings
There are three important parts of division operation :
Sign of the result.
Integral part
Decimal part
Also, there are few corner cases where you need to deal with the fact that Integer.MIN_VALUE is greater than Integer.MAX_VALUE when compared in absolute form.
For example : -2147483648/-1 can't yield 2147483648 when divided in the form of integer types. The reason is simple. The type of the resulting type will be integer type, and the maximum positive value that a integer type variable can hold is +2147483647
To mitigate that scenario, we should at first convert both the numerator and denominator into their long positive form. That gives us the integral part of the answer.
The XOR of two numbers will have the sign bit as 1 only in case they have opposite signs. That solves the first part (sign of result) of the problem.
For decimal part, we can employ the general division rule i.e. multiply the remainder with 10 and try dividing again and repeat. Keep record of the remainder we have already come across to prevent the loop from going into unbounded iterations.
public String fractionToDecimal(int A, int B) {
StringBuilder sb = new StringBuilder((A^B) < 0 ? "-" : "");
long a = Math.abs((long)A);
long b = Math.abs((long)B);
sb.append(Long.toString(a/b));
long rem = a % b;
sb.append((rem != 0) ? "." : "");
Map<Long, Integer> remainderMap = new HashMap<>();
int pos = 0;
while (rem != 0){
sb.append(Long.toString((rem*10)/b));
remainderMap.put(rem, pos++);
rem = (rem*10) % b;
if (remainderMap.containsKey(rem)){
String currNum[] = sb.toString().split("\\.");
return currNum[0] + "." + currNum[1].substring(0, remainderMap.get(rem)) +
"(" + currNum[1].substring(remainderMap.get(rem)) + ")";
}
}
if (sb.toString().equals("-0")) return "0";
return sb.toString();
}
Sample output :
2/3 gives 0.(6)
-2147483648/-1 gives 2147483648

Categories

Resources