Okay, so I just started this homework lab and I'm having a little bit of trouble. I've searched for any solutions but they all seem way more complex than what I can comprehend. I'm looking for the dollars needed and change needed to buy something. I just came up with some numbers and when i run the file i get an error. Can anyone help me find how to complete the equations to get the sum value. Also dollarsNeeded needs to be int and not double. The changeNeeded can be double. Any help would be greatly appreciated.
java:30: error: possible loss of precision
findDollars = xboxOne + newGame;
^
required: int
found: double
1 error
public class MoneyNeeded
{
public static void main(String[] args)
{
double xboxOne, newGame, moneyNeeded;
xboxOne = 320.41;
newGame = 64.36;
moneyNeeded = findMoney(xboxOne, newGame);
System.out.println(moneyNeeded);
int dollarsNeeded;
dollarsNeeded = findDollars(xboxOne, newGame);
System.out.println(dollarsNeeded);
double changeNeeded;
changeNeeded = findChange(xboxOne, newGame);
System.out.println(changeNeeded);
}
public static double findMoney(double xboxOne, double newGame)
{
double findMoney;
findMoney = xboxOne + newGame;
return findMoney;
}
public static int findDollars(double xboxOne, double newGame)
{
int findDollars;
findDollars = xboxOne + newGame;
return findDollars;
}
public static double findChange(double findDollars, double findMoney)
{
double findChange;
findChange = findMoney % findDollars;
return findChange;
}
}
So you can do :
findDollars = xboxOne.intValue() + newGame.intValue();
or
findDollars = (int)(xboxOne + newGame);
You can't sum two doubles and put the result in an int, because the int cannot contain the decimal part, so you will .. well .. loose precision.
If you are ok with loosing the decimal part, you can explicitly drop it in away :
findDollars = (int)(xboxOne + newGame); // Simply truncate the decimal part away
But usually is not a good idea, cause 0.2 + 0.2 will return 0.
I think your having issues because you're using datatypes as parameter for your methods, when they should be used for arguments in the method. I' m not sure though, so make sure to double check this.
Related
Does there exist, or can you create, a fast method A() which converts a double to a long such that:
A(0d) = 0L
A(Math.nextUp(0d)) = 1L
A(Math.nextUp(Math.nextUp(0d))) = 2L
A(Math.nextUp(Math.nextUp(Math.nextUp(0d)))) = 3L
...
A(Double.MAX_VALUE) = Long.MAX_VALUE
A(-Double.MAX_VALUE) = -Long.MAX_VALUE
EDIT:
Just found an adequate answer myself. First of all the above is not quite possible due to the existence of NaN and infinity for double. The fact that Long does not have these means that Long.MAX_VALUE is larger than the amount of double bit permutations that create actual numbers.
However, despite this my usecase is actually just that I want a conversion that maps double to long while being order-preserving. As long as I don't encounter NaN or infinity I guess I should be able to just reinterpret double to long.
Double.doubleToLongBits(value)
Math.nextUp() will increase the fractional part not the whole part. To get the desired output, you have to call a() for each Math.nextUp().
public class D2L {
public static Long a(double input) {
return Math.round(Math.ceil(input));
}
public static void main(String[] args) {
System.out.println(a(0d)); //0L
System.out.println(a(Math.nextUp(a(0d)))); //1L
System.out.println(a(Math.nextUp(a(Math.nextUp(a(0d)))))); //2L
System.out.println(a(Math.nextUp(a(Math.nextUp(a(Math.nextUp(a(0d)))))))); //3L
System.out.println(a(Double.MAX_VALUE) + " = " +Long.MAX_VALUE); //9223372036854775807 = 9223372036854775807
System.out.println(-a(Double.MAX_VALUE) + " = " + -Long.MAX_VALUE); //-9223372036854775807 = -9223372036854775807
}
}
For some reason when I run the file the answer seems to be 0. I'm still fairly new to Java so could someone explain to me what I've done wrong.. It all seems fine to me.
public class bus {
public static void main(String[] args) {
bus fivePM = new bus(23, 120);
bus elevenAM = new bus(27, 140);
System.out.println(fivePM.gallonsUsed());
System.out.println(elevenAM.gallonsUsed());
}
private int mpg;
private int milesTravelled;
private double used;
public bus(int mpg, int milesTravelled){
this.mpg = mpg;
this.milesTravelled = milesTravelled;
}
public double gallonsUsed(){
this.used = this.mpg/this.milesTravelled;
return this.used;
}
}
In both of your instantiated bus objects, milesTravelled is less than mpg.
When you divide an int by an int, you get an int.
this.mpg/this.milesTravelled;
This will return 0 because the digits after the decimal point don't matter if it's an int.
To make them not ints, you could do things like:
this.mpg * 1.0 / this.milesTravelled
or
this.mpg/((double) this.milesTravelled)
As mentioned, diving ints gives an integer number. You can change type types of mpg and milesTravelled to double. Also you should be inverting the answer. m/g divided by m = m/mg = 1/g, not g. For example, at 10mpg traving 20m would use 2 gallons, but your calculation would give 1/2 gallon.
Use double instead of int or just carefully convert your int into a double before doing any division. This is a common problem for Java novices. Take a look at this and this. Try this out:
private double mpg;
private double milesTravelled;
private double used;
public bus(double mpg, double milesTravelled){
this.mpg = mpg;
this.milesTravelled = milesTravelled;
}
NOTE 1: When you do the division, make sure you check to see if milesTravelled is equal to 0 or not. If it is, then you will get an Exception.
NOTE 2: Change bus to Bus in the header definition of bus (which then means you will use Bus instead of bus). Using the capital letter in the beginning of a custom Object's name is a relatively common standard.
trying to get back into Java and have decided to tackle PI. So I made this program based on the Harmonic Series:
public static void main(String [] args)
{
double denominator = 1.0;
double tempValue;
double PI = 0.0;
// End point for program
double stopPoint = 1234.5;
for( int i = 1; i < stopPoint; i++ )
{
tempValue = Math.sqrt( (1/(denominator*denominator))/6 );
PI = PI + tempValue;
denominator = denominator + 1.0;
}
System.out.println( "PI = " + PI );
The application prints this:
PI = 3.1417306496998294
So you can see its mildly working. But when I change the stopPoint value any more I'm not getting a change in precision, at all.
For example changing it to 1234.75 gives the same answer - or perhaps print can't display the exact value? If so what is the best way to print out values like these?
Thanks
EDIT
I've added this code as its a change to the code posted above. Some of the changes include the use of Big Decimal and the inclusion of a while loop instead of a for.
import java.math.BigDecimal;
import java.math.MathContext;
public class MyPI
{
final static BigDecimal ONE = new BigDecimal(1);
final static BigDecimal SIX = new BigDecimal(6);
public static void main(String [] args)
{
BigDecimal deno, temp, tempPI;
int start, end;
start = 1;
end = 500000;
temp = new BigDecimal(0);
// Starting denominator point
deno = ONE;
while( start < end )
{
// Without precision and rounding mode, it will try to return a
// never ending number
temp = temp.add( ONE.divide(deno.pow(2),MathContext.DECIMAL64) );
deno = deno.add(ONE);
start = start + 1;
}
tempPI = temp.multiply(SIX);
// Need to convert to double for square root
double PI = Math.sqrt( tempPI.doubleValue() );
System.out.println( "PI: " + PI );
}
}
This produces the following result:
PI: 3.1415907437318054
Thanks all for the help - will probably add a timer to track how long it takes to do this.
I've been using the BigDecimal type instead of the double, but I have hit a bit of a roadblock—the square root.
Don't take the square root of each term. As shown in this example, add the terms of the series, which has the exact sum π2/6. When your loop terminates, multiply by six and then take a single square root.
If you want more precision, you can use Java's BigDecimal.
Use Java BigDecimal instead of Double that has a limited precision.
The BigDecimal class can give you "arbitrary-precision signed decimal numbers", which is what you want in this case, although the instances of BigDecimal are a little more tricky to work with than literals, the class actually works quickly and can be used to do what you need fairly accurately.
Just for your information, though, using the harmonic series to calculate Pi is pretty inefficient, but I understand doing it as a fun program or to learn something new.
I know this question is repeated alot, but please have a look at the statement first than mark it already answered :)
For truncating the double values 2 decimal places I use two ways which are mostly mentioned everywhere. They are given below
//this one
DecimalFormat dtime = new DecimalFormat("#.##");
return Double.valueOf(dtime.format(val));
//or the one below
BigDecimal bd = new BigDecimal(val);
BigDecimal rounded = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
return rounded.doubleValue();
The problem is that for both the ways I mostly get correct rounded values in the dataset. But strangely at the same time I get values like 2.00000000000005 or 19.97999999999.
The problem that I dont get is that why only a few values are not rounded of. What could be wrong?
For truncating the double values 2 decimal places I use two ways which are mostly mentioned everywhere.
And they are both wrong, because they are attempting the impossible. There is no such thing as truncating a double to 2 decimal places, because doubles don't have decimal places. They have binary places. See my answer here for proof. If you want decimal places you have to use a decimal radix, i.e. BigDecimal or DecimalFormat.
Issue is that floating point numbers are inherently approximate in nature, given the underlying representation. Therefore you will want to use them in places where approximations are good, and avoid them where approximations are no good (e.g. financials).
The call to rounded.doubleValue() still returns a floating point number and so it is still impacted by the limitations of the representation.
See
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
for more information.
The following piece of code helped me in restricting the number of decimal places (truncating) for a double value.
public static Double truncate (double valueToTruncate, int numberOfDecimalPlaces) {
if (valueToTruncate > 0) {
return new BigDecimal(String.valueOf(valueToTruncate)).setScale(numberOfDecimalPlaces, BigDecimal.ROUND_FLOOR).doubleValue();
} else {
return new BigDecimal(String.valueOf(valueToTruncate)).setScale(numberOfDecimalPlaces, BigDecimal.ROUND_CEILING).doubleValue();
}
}
Hope this helps someone :)
I'm new to this but keeping everything in front of me I did it this way. Now mind you this is a truncation mathematically, I don't convert to string except in my debugs after each line.
It isn't elegant but seems to work. This is purely a problem solving framework.
Anyway;
import java.util.Scanner;
public class TestConstructs
{
private static double w;
private static int w1;
private static double w2;
private static double w3;
private static int w4;
private static double w5;
private static double w6;
public static void main(String[] args)
{
// TODO Auto-generated method stub
TestConstructs foo = new TestConstructs();
foo.setWage(w);
}
public void setWage(double w)
{
Scanner input = new Scanner(System.in);
System.out.println("Enter Wage: "); //enter something longish like 30987.978654 or w/e
w = input.nextDouble();
w1 = (int)w;
System.out.printf("%d w1\n",w1);
w2 = w - w1;
System.out.printf("%.3f w2\n",w2);
w3 = w2*100;
System.out.printf("%.3f w3\n",w3);
w4 = (int)w3;
System.out.printf("%d w4\n",w4);
w5 = (double)w4;
System.out.printf("%.3f w5\n",w5);
w6 = 0 + w5/100;
System.out.printf("%.3f w6\n",w6);
w = w1 + w6;
System.out.printf("%.3f final value\n",w); //.3 to show zero
input.close();
}
}
What I got at the end
Enter Wage:
30987.978654
30987 w1
0.979 w2
97.865 w3
97 w4
97.000 w5
0.970 w6
30987.970 final value
I have to store the product of several probabilty values that are really low (for example, 1E-80). Using the primitive java double would result in zero because of the underflow. I don't want the value to go to zero because later on there will be a larger number (for example, 1E100) that will bring the values within the range that the double can handle.
So, I created a different class (MyDouble) myself that works on saving the base part and the exponent parts. When doing calculations, for example multiplication, I multiply the base parts, and add the exponents.
The program is fast with the primitive double type. However, when I use my own class (MyDouble) the program is really slow. I think this is because of the new objects that I have to create each time to create simple operations and the garbage collector has to do a lot of work when the objects are no longer needed.
My question is, is there a better way you think I can solve this problem? If not, is there a way so that I can speedup the program with my own class (MyDouble)?
[Note: taking the log and later taking the exponent does not solve my problem]
MyDouble class:
public class MyDouble {
public MyDouble(double base, int power){
this.base = base;
this.power = power;
}
public static MyDouble multiply(double... values) {
MyDouble returnMyDouble = new MyDouble(0);
double prodBase = 1;
int prodPower = 0;
for( double val : values) {
MyDouble ad = new MyDouble(val);
prodBase *= ad.base;
prodPower += ad.power;
}
String newBaseString = "" + prodBase;
String[] splitted = newBaseString.split("E");
double newBase = 0; int newPower = 0;
if(splitted.length == 2) {
newBase = Double.parseDouble(splitted[0]);
newPower = Integer.parseInt(splitted[1]);
} else {
newBase = Double.parseDouble(splitted[0]);
newPower = 0;
}
returnMyDouble.base = newBase;
returnMyDouble.power = newPower + prodPower;
return returnMyDouble;
}
}
The way this is solved is to work in log space---it trivialises the problem. When you say it doesn't work, can you give specific details of why? Probability underflow is a common issue in probabilistic models, and I don't think I've ever known it solved any other way.
Recall that log(a*b) is just log(a) + log(b). Similarly log(a/b) is log(a) - log(b). I assume since you're working with probabilities its multiplication and division that are causing the underflow issues; the drawback of log space is that you need to use special routines to calculate log(a+b), which I can direct you to if this is your issue.
So the simple answer is, work in log space, and re-exponentiate at the end to get a human-readable number.
You trying to parse strings each time you doing multiply. Why don't you calculate all values into some structure like real and exponential part as pre-calculation step and then create algorithms for multiplication, adding, subdivision, power and other.
Also you could add flag for big/small numbers. I think you will not use both 1e100 and 1e-100 in one calculation (so you could simplify some calculations) and you could improve calculation time for different pairs (large, large), (small, small), (large, small).
You can use
BigDecimal bd = BigDecimal.ONE.scaleByPowerOfTen(-309)
.multiply(BigDecimal.ONE.scaleByPowerOfTen(-300))
.multiply(BigDecimal.ONE.scaleByPowerOfTen(300));
System.out.println(bd);
prints
1E-309
Or if you use a log10 scale
double d = -309 + -300 + 300;
System.out.println("1E"+d);
prints
1E-309.0
Slowness might be because of the intermediate string objects which are created in split and string concats.
Try this:
/**
* value = base * 10 ^ power.
*/
public class MyDouble {
// Threshold values to determine whether given double is too small or not.
private static final double SMALL_EPSILON = 1e-8;
private static final double SMALL_EPSILON_MULTIPLIER = 1e8;
private static final int SMALL_EPSILON_POWER = 8;
private double myBase;
private int myPower;
public MyDouble(double base, int power){
myBase = base;
myPower = power;
}
public MyDouble(double base)
{
myBase = base;
myPower = 0;
adjustPower();
}
/**
* If base value is too small, increase the base by multiplying with some number and
* decrease the power accordingly.
* <p> E.g 0.000 000 000 001 * 10^1 => 0.0001 * 10^8
*/
private void adjustPower()
{
// Increase the base & decrease the power
// if given double value is less than threshold.
if (myBase < SMALL_EPSILON) {
myBase = myBase * SMALL_EPSILON_MULTIPLIER;
myPower -= SMALL_EPSILON_POWER;
}
}
/**
* This method multiplies given double and updates this object.
*/
public void multiply(MyDouble d)
{
myBase *= d.myBase;
myPower += d.myPower;
adjustPower();
}
/**
* This method multiplies given primitive double value with this object and update the
* base and power.
*/
public void multiply(double d)
{
multiply(new MyDouble(d));
}
#Override
public String toString()
{
return "Base:" + myBase + ", Power=" + myPower;
}
/**
* This method multiplies given double values and returns MyDouble object.
* It make sure that too small double values do not zero out the multiplication result.
*/
public static MyDouble multiply(double...values)
{
MyDouble result = new MyDouble(1);
for (int i=0; i<values.length; i++) {
result.multiply(values[i]);
}
return result;
}
public static void main(String[] args) {
MyDouble r = MyDouble.multiply(1e-80, 1e100);
System.out.println(r);
}
}
If this is still slow for your purpose, you can modify multiply() method to directly operate on primitive double instead of creating a MyDouble object.
I'm sure this will be a good deal slower than a double, but probably a large contributing factor would be the String manipulation. Could you get rid of that and calculate the power through arithmetic instead? Even recursive or iterative arithmetic might be faster than converting to String to grab bits of the number.
In a performance heavy application, you want to find a way to store basic information in primitives. In this case, perhaps you can split the bytes of a long or other variable in so that a fixed portion is the base.
Then, you can create custom methods the multiply long or Long as if they were a double. You grab the bits representing the base and exp, and truncate accordingly.
In some sense, you're re-inventing the wheel here, since you want byte code that efficiently performs the operation you're looking for.
edit:
If you want to stick with two variables, you can modify your code to simply take an array, which will be much lighter than objects. Additionally, you need to remove calls to any string parsing functions. Those are extremely slow.