Why is my formatting so strange? - java

I have a problem with my code's formatting. At the end, it's supposed to print out its results. I am using a printf statement, but it returns numbers that aren't as precise as I need them to be. For example, if one number should be 76.83200000000001, it returns as 76.83200. It is also adding unnecessary zeros at the end of numbers, and if a number should be 28.0, it turns into 28.000000. If possible, can we do this without a BigDecimal variable? Here's my code so far (NOTE: there are spaces in front of some strings, that's because the website I'm submitting to requires that for some reason):
import java.util.Scanner;
public class Population {
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
double startingNumber, dailyIncrease, daysWillMultiply, temp, population;
System.out.print("Enter the starting number organisms: ");
startingNumber = stdin.nextDouble();
while(startingNumber < 2) {
System.out.print("Invalid. Must be at least 2. Re-enter: ");
startingNumber = stdin.nextDouble();
}
System.out.print("Enter the daily increase: ");
dailyIncrease = stdin.nextDouble();
while(dailyIncrease < 0) {
System.out.print("Invalid. Enter a non-negative number: ");
dailyIncrease = stdin.nextDouble();
}
System.out.print("Enter the number of days the organisms will multiply: ");
daysWillMultiply = stdin.nextDouble();
while(daysWillMultiply < 1) {
System.out.print("Invalid. Enter 1 or more: ");
daysWillMultiply = stdin.nextDouble();
}
temp = startingNumber * dailyIncrease;
population = startingNumber;
System.out.println("Day\t\tOrganisms");
System.out.println("-----------------------------");
System.out.println("1\t\t" + startingNumber);
for (int x = 2; x <= daysWillMultiply; x++) {
population += temp;
temp = population * dailyIncrease;
System.out.printf(x + "\t\t%f\n", population);
}
}
}

Well, I deleted my previous answer as it was absolutely wrong (thanks to #JohnKugelman for pointing this out). I thought that precision is lost due to converting to float, but it is not true.
According to the formatter documentation, here's what happens when %f flag is used:
The magnitude m (absolute value of the argument) is formatted as
the integer part of m, with no leading zeroes, followed by the
decimal separator followed by one or more decimal digits representing
the fractional part of m.
The number of digits in the result for the fractional part of m is equal to the precision. If the precision is not specified then
the default value is 6
If the precision is less than the number of digits which would appear
after the decimal point in the string returned by
Float.toString(float) or Double.toString(double) respectively,
then the value will be rounded using the round half up algorithm.
Otherwise, zeros may be appended to reach the precision.
That's why you get unnecessary zeros and cut digits.
The documentation suggests to use Float.toString(float) or Double.toString(double) for a canonical representation of the value.
If you want to use System.out.printf(...);, you can just replace your %f flag with %s - in this case the argument will be converted to a string (the result is obtained by invoking the argument's toString() method, and this is what you need). For example, you could rewrite this line:
System.out.printf(x + "\t\t%f\n", population);
as follows:
System.out.printf("%d\t\t%s\n", x, population);
This will print the exact value of your population.

Check first answer of this thread, it maybe helpful.
How many significant digits have floats and doubles in java?
It's important to understand that the precision isn't uniform and that
this isn't an exact storage of the numbers as is done for integers.

Related

How can I change 8 digit number's last digit with just using primitive data types?

This is the question.
An alien spaceship broadcasts a frequency of digital signals that can be
converted into 0-1 digits (always a 8 digit combination). In brief, a stream of digits entered via the console is supposed to be caught. It is obvious that the digits we acquire can be converted into base ten - decimal. The situation here is the noise which interferes with the original signal that we are listening to. Signal noise, which negates the last item of the stream, may appear in the very first character of your input stream. All of the characters must be either 0 or 1, otherwise it is a noise. Every first character is always 0. The input stream will be taken as a single set of numeric characters.
I changed too many thing in code and still it is not working with all numbers. But I got the message from these codes:
01000110
21010011
21001000
01000101
01001110
51000101
when we converted these to correct version it'll give the message. For example these give "FRIEND". I found this but program is not working with 00000000. It gives error. How can I correct this.
Scanner inp = new Scanner(System.in);
int frequency = inp.nextInt();
int digit1 = frequency/10000000;
int digit2 = (frequency/1000000)%10;
int digit3 = (frequency/100000)%10;
int digit4 = (frequency/10000)%10;
int digit5 = (frequency/1000)%10;
int digit6 = (frequency/100)%10;
int digit7 = (frequency/10)%10;
int digit8 = frequency%10;
int decimal_version = digit1*10000000 + digit2*1000000 + digit3*100000 + digit4*10000 + digit5*1000 + digit6*100 + digit7*10 + digit8;
System.out.println(decimal_version);
Change the last bit of 8-digit number:
num ^= 1B

Program to count number of digits in a double following decimal point in Java

Below is a program that is supposed to count the number of digits in a double value following the decimal point. On entering some double values, the program tends to start an infinite loop (possibly due to floating-point imprecision). I do not want to use any wrapper methods (including String class). Could someone possibly provide an explanation for the endless loop for certain inputs and provide a solution?
import java.util.*;
class Flt
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
System.out.print("Enter a double number: ");
double f = sc.nextDouble();
double tmp = f;
int len = 0;
while(tmp != (int) tmp)
{
tmp *= 10;
len++;
}
System.out.println(len);
}
}
The problem overflows in the conversion to int, so tmp != (int) tmp is never true.
Consider a user input of “3.1415”. 3.1415 is not representable in the double format, so it is converted to the nearest representable value, 3.141500000000000181188397618825547397136688232421875. First, this has so many decimal digits that, even if the multiplications by ten were performed with exact real-number arithmetic, they would not produce an integer result until the number reached 3141500000000000181188397618825547397136688232421875. However, that number cannot be converted to int without overflow, because it is too large to be represented in an int. The conversion yields the largest value representable in int, 2147483647. Then comparing the number 3141500000000000181188397618825547397136688232421875 to the result of the conversion, 2147483647, indicates they are unequal, and the loop continues.
In fact, the multiplications by ten are not performed with exact real-number arithmetic. In each multiplication, the result is rounded to the nearest value representable in double. So the first yields 31.415000000000002700062395888380706310272216796875, the next 314.15000000000003410605131648480892181396484375, and so on. The first integer result is 31415000000000004. Again, this is too large to represent in an int, so tmp != (int) tmp is evaluated as 31415000000000004 != 2147483647, which is of course true, so the loop continues.
The infinite loop can be resolved by eliminating the conversion to int. For example, the test expression can be replaced by tmp % 1 != 0 to loop as long as tmp has a remainder when divided by 1 (hence is not an integer). However, then an input of “3.1415” yields 16—it does not count the number of decimal places in either the user’s input or the double that results from scanning it but rather the number of iterations until the multiplications with rounding yield an integer.
Once the user’s input has been converted to a double, there is no way to properly count the number of decimal places in the user’s input because the original value is lost. If the user enters either “3.1415” or “ 3.141500000000000181188397618825547397136688232421875”, the resulting double will be 3.141500000000000181188397618825547397136688232421875, so it is not possible to tell what the original number was. To count the number of decimal places in the user’s input, reading it as a string, looking for the decimal point, and count the digit characters after it (excluding trailing zeros if desired).

OutOfBounds Exception ; working with Fractions

I'm writing a program called FractionScaler that takes in a fraction from the user using Scanner, and then manipulates it. I've written a fraction class that handles all the calculations. The user is supposed to enter a fraction like this: "2/3" or "43/65" etc... This part works fine, the problem is when there is space between the integers: " 3 / 4 " or "2/ 5" etc... An "OutOfBoundsException: String index out of range: -1" occurs. Let me explain further.
//This is the user inputted fraction. i.e. "2/3" or " 3 / 4"
String frac = scan.next();
//This finds the slash separating the numerator from the denominator
int slashLocate = frac.indexOf("/");
//These are new strings that separate the user inputted string into two parts on
//either side of the "/" sign
String sNum = frac.substring(0,slashLocate); //This is from the beginning of string to the slash (exclusive)
String sDenom = frac.substring(slashLocate+1,frac.length()); //from 1 after slash to end of string
//This trims the white space off of either side of the integers
sNum = sNum.trim(); //Numerator
sDenom = sDenom.trim(); //Denominator
What I thought should be left is just two strings that look like integers, now I need to turn those strings into actual integers.
//converts string "integer" into real int
int num = Integer.parseInt(sNum);
int denom = Integer.parseInt(sDenom);
Now that I have two integers for the numerator and the denominator, I can plug them into a constructor for the fraction class I wrote.
Fraction fraction1 = new Fraction(num, denom);
I doubt this is the best way to go about this, but it is the only way I could think of. When the user inputted fraction has no spaces, EX. "2/3" or "5/6" , the program works fine.
When the user input has spaces of any kind, EX. "3 / 4" or " 3 /4" , the following error is shown:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1.
The terminal points to line 17 of my code which is this line above:
String sNum = frac.substring(0,slashLocate);
I don't know why I'm getting an out of bounds error. Can anyone else figure it out?
If something is unclear or I didn't give enough info, just say so.
Thanks very much.
Try String frac = scan.nextLine();
I think next() won't get anything after a space.
From the documentation:
A Scanner breaks its input into tokens using a delimiter pattern,
which by default matches whitespace.
That means this won't work, because when entering 2 / 3, frac will just contain the text "2":
String frac = scan.next();
//This finds the slash separating the numerator from the denominator
int slashLocate = frac.indexOf("/");

Separate double number larger than 10 digits in Java

I have written a code that separate a double number into whole and fraction part, but it gives the correct answer for number upto 10 digits only (decimal part+fraction part), how do i separate double number larger than 10 digits?
double num, temp;
int j=1;
int whole,frac;
num= 122.007094;
temp= num;
whole=(int)num;
// FOR THE FRACTION PART
do{
j=j*10;
}while((temp*j)%10!=0);
j=j/10;
frac= (int)(num*j)-(whole*j);
System.out.println("Double number= "+num);
System.out.println("Whole part= "+whole+" fraction part= "+frac);
Perhaps you could use java.lang.Math.floor(double) for the integer part, and then subtract that from the original number to get the fractional part. (If that doesn't do what you want for negative numbers, then use Math.ceiling(double) for the integer part when the number is negative.)
Here is an attempt at what I think you want. I've left the results in String form both to preserve leading zeros in the fraction part, and to avoid overflow. If you want to do arithmetic, rather than display, I recommend converting the String results to BigInteger, which will not overflow.
import java.math.BigDecimal;
public class Test{
public static void main(String[] args){
double num1 = 122.007094;
double num2 = 1236758511.98746514;
testIt(num1);
testIt(num2);
testIt(1e7);
testIt(0.1);
testIt(0.12345678901234);
}
public static void testIt(double in) {
String[] result = doubleSplit(in);
System.out.println("num="+in+" whole="+result[0]+" fraction="+result[1]);
}
/**
* Split the decimal representation of a double at where the decimal point
* would be. The decimal representation is rounded as for Double.toString().
* #param in The double whose decimal representation is to be split.
* #return A two element String[]. The first element is the part
* before where the decimal point would be. The second element is the part
* after where the decimal point would be. Each String is non-empty, with
* "0" for the second element for whole numbers.
*/
public static String[] doubleSplit(double in) {
/* Use BigDecimal to take advantage of its toPlainString. The
* initial Double.toString uses its rounding to limit the
* number of digits in the result.
*/
BigDecimal bd = new BigDecimal(Double.toString(in));
String [] rawSplit = bd.toPlainString().split("\\.");
if(rawSplit.length > 1){
return rawSplit;
} else {
return new String[]{rawSplit[0], "0"};
}
}
}
The output:
num=122.007094 whole=122 fraction=007094
num=1.2367585119874651E9 whole=1236758511 fraction=9874651
num=1.0E7 whole=10000000 fraction=0
num=0.1 whole=0 fraction=1
num=0.12345678901234 whole=0 fraction=12345678901234

Primitive type decimal in Java - User Entry

I am doing an exercise in which the user has to input a signed four digit decimal number such as +3364, -1293, +0007, etc using Java programming language.
As far as I know, Java does not support a primitive type decimal.
My questions are:
How can I enter numbers like above?
How can I provide a +, - sign for the above numbers?
UPDATE
The code below shows a snippet in which it asks the user to enter a valid number (no characters) - the unary + is not working using the code below!! is there a way to fix it.
public int readInt() {
boolean continueLoop = true;
int number = 0;
do {
try {
number = input.nextInt();
continueLoop = false;
} // end try
catch (InputMismatchException inputMismatchException) {
input.nextLine();
/** discard input so user can try again */
System.out.printf("Invalid Entry ?: ");
} // end of catch
} while (continueLoop); // end of do...while loop
return number;
} // end of method readInt()
Java has 8 primitive (non-Object/non-Reference) types:
boolean
char
byte
short
int
long
float
double
If, by "decimal" you mean "base 10 signed integer", then yes, Java supports that via byte, short, int and long. Which one you use will depend on the input ranges, but int is the most common, from what I've seen.
If, by "decimal" you mean "base 10 signed floating-point number with absolute precision" similar to C#'s Decimal type, then no, Java does not have that.
If Scanner.nextInt is throwing an error for you, like it is me, then the following should work:
/* Create a scanner for the system in. */
Scanner scan = new Scanner(System.in);
/*
* Create a regex that looks for numbers formatted like:
*
* A an optional '+' sign followed by 1 or more digits; OR A '-'
* followed by 1 or mored digits.
*
* If you want to make the '+' sign mandatory, remove the question mark.
*/
Pattern p = Pattern.compile("(\\+?(\\d+))|(\\-\\d+)");
/* Get the next token from the input. */
String input = scan.next();
/* Match the input against the regular expression. */
Matcher matcher = p.matcher(input);
/* Does it match the regular expression? */
if (matcher.matches()) {
/* Declare an integer. */
int i = -1;
/*
* A regular expression group is defined as follows:
*
* 0 : references the entire regular expression. n, n != 0 :
* references the specified group, identified by the nth left
* parenthesis to its matching right parenthesis. In this case there
* are 3 left parenthesis, so there are 3 more groups besides the 0
* group:
*
* 1: "(\\+?(\\d+))"; 2: "(\\d+)"; 3: "(\\-\\d+)"
*
* What this next code does is check to see if the positive integer
* matching capturing group didn't match. If it didn't, then we know
* that the input matched number 3, which refers to the negative
* sign, so we parse that group, accordingly.
*/
if (matcher.group(2) == null) {
i = Integer.parseInt(matcher.group(3));
} else {
/*
* Otherwise, the positive group matched, and so we parse the
* second group, which refers to the postive integer, less its
* '+' sign.
*/
i = Integer.parseInt(matcher.group(2));
}
System.out.println(i);
} else {
/* Error handling code here. */
}
Alternatively, you can do it like this:
Scanner scan = new Scanner(System.in);
String input = scan.next();
if (input.charAt(0) == '+') {
input = input.substring(1);
}
int i = Integer.parseInt(input);
System.out.println(i);
Basically just remove the '+' sign if there's one and then parse it. If you're going to be doing programming, learning regular expressions is very useful, which is why I gave you that, instead. But if this is homework and you're worried that the teacher will get suspicious if you use something that is beyond the scope of the course, then by all means do not use the regular expression approach.
Use Scanner:
Scanner scan = new Scanner(System.in);
System.out.print("Enter 3 integer numbers: ");
int a = scan.nextInt();
int b = scan.nextInt();
int c = scan.nextInt();
System.out.print("You have entered: " + a + " | " + b + " | " + c);
OUTPUT:
Enter 3 integer numbers: +3364 -1293 +0007
You have entered: 3364 | -1293 | 7
A side note: Be careful when you are using leading 0's with integer numbers like 0007, because it's interpreted in Java as octal number not decimal number. So, 010 is actually 8 in decimal base system, not 10.
System.out.print(010);
OUTPUT:
8
UPDATE:
Note that Scanner requires the signs + and - to be sticked to the number like +5432 and -5432, not as + 5432 nor - 5432.
You can use the Scanner class to read the values. You will have to do a bit more work to ensure that + is not part of your conversion to Integer (check the Integer wrapper class), as Scanner won't accept + as a unary operator (it works fine with negative).
Take a look at fixed point numbers. The DecimalFormat class can format this for you.

Categories