I am trying to create the number 0.00000.... with as many '0' as the user input wants. What is wrong with my code below?
int n;
double dec = 0.0;
in = new Scanner(System.in);
n = in.nextInt();
for (i = 1; i <= n; i++)
dec = dec / 10.0d;
Number doesn't change.
You're expecting double to retain the number of decimal digits - it doesn't do that. The value is always normalized. The double type is all about the magnitude of a number, not a particular decimal representation. It's suitable for naturally occurring quantities - weights, heights etc.
If you care about decimal digits, then BigDecimal is a more suitable type for you. This is more appropriate for currency values for example, where there really is a precise amount specified as a decimal representation.
BigDecimal does retain the number of decimal digits you use, but you'll need to be careful about exactly how you use it. You'll no doubt find the setScale method useful.
For example:
import java.math.BigDecimal;
class Test {
public static void main(String[] args) throws Exception {
BigDecimal x = new BigDecimal("0")
System.out.println(x); // 0
x = x.setScale(5);
System.out.println(x); // 0.00000
}
}
If you just want to display the decimal point according to user input, Try
int n;
double dec = 0.0;
in = new Scanner(System.in);
n = in.nextInt(); //number of decimal places
System.out.println(String.format("%."+n+"f",dec));
0.0, 0.00, 0.0000000000000000000000000000000000000000000000 and so on are exactly the same value; Java literally can't tell them apart during runtime. No matter how many times you divide it by 10, it will remain EXACTLY the same number.
When being printed, trailing zero digits are omitted (unless explicitly specified in, for instance, String.format).
Basically, what you are trying to do is keep on dividing 0.0. But it'll always give you the same result as Java considers 0.000 as 0.0. Even 0.0000000000000000 will be considered as 0.0. If you just want to display that many 0s, then save it in a String and then display.
...
StringBuilder s = new StringBuilder("0.");
for(int i = 1; i < n; i++)
s.append("0");
String num = s.toString();
//Then use it.
If you need string with user defined '0':
public static String FormatZero( int accurancy_ ) throws IllegalArgumentException
{
if( 0 >= accurancy_ )
{
throw new IllegalArgumentException( "accurancy_must be > 0" );
}
String formatString = "0.";
for( int i = 0 ; i < accurancy_ ; ++i )
{
formatString += "0";
}
DecimalFormat format = new DecimalFormat( formatString );
String result = format.format( 0d );
return result;
}
Related
When analysing data sets, such as data for human heights or for human weights, a common step is to adjust the data. This adjustment can be done by normalizing to values between 0 and 1, or throwing away outliers.
For this program, adjust the values by dividing all values by the largest value. The input begins with an integer indicating the number of floating-point values that follow. Assume that the list will always contain fewer than 20 floating-point values.
Output each floating-point value with two digits after the decimal point, which can be achieved as follows:
System.out.printf("%.2f", yourValue);
Ex: If the input is:
5 30.0 50.0 10.0 100.0 65.0
the output is:
0.30 0.50 0.10 1.00 0.65
The 5 indicates that there are five floating-point values in the list, namely 30.0, 50.0, 10.0, 100.0, and 65.0. 100.0 is the largest value in the list, so each value is divided by 100.0.
For coding simplicity, follow every output value by a space, including the last one.
This is my code so far:
import java.util.Scanner;
public class LabProgram {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
double numElements;
numElements = scnr.nextDouble();
double[] userList = new double[numElements];
int i;
double maxValue;
for (i = 0; i < userList.length; ++i) {
userList[i] = scnr.nextDouble();
}
maxValue = userList[i];
for (i = 0; i < userList.length; ++i) {
if (userList[i] > maxValue) {
maxValue = userList[i];
}
}
for (i = 0; i < userList.length; ++i) {
userList[i] = userList[i] / maxValue;
System.out.print(userList[i] + " ");
System.out.printf("%.2f", userList[i]);
}
}
}
I keep getting this output.
LabProgram.java:8: error: incompatible types: possible lossy conversion from double to int
double [] userList = new double [numElements];
^
1 error
I think my variable is messed up. I read through my book and could not find help. Can someone please help me on here. Thank you so much! This has been very stressful for me.
The specific error message is because the index and size of an element must be int. So declare and assign at once: int numElements = scnr.nextInt();
Better way of programming things:
skip manual input (aka Scanner and consorts). Makes you crazy and testing a 100'000'000 times slower
you can integrate the interactive part later, once the method is done. You already know how, your code already shows.
use an explicit method to do your work. Don't throw everything into the main method. This way you can run multiple examples/tests on the method, and you have a better implementation for later.
check for invalid input INSIDE the method that you implement. Once you can rely in such a method, you can keep on using it later on.
you could even move the example numbers to its own test method, so you can run multiple test methods. You will learn about Unit Testing later on.
Example code:
public class LabProgram {
public static void main(final String[] args) {
final double[] initialValues = new double[] { 30.0, 50.0, 10.0, 100.0, 65.0 };
final double[] adjustedValues = normalizeValuesByHighest(initialValues);
System.out.println("Adjusted values:");
for (final double d : adjustedValues) {
System.out.printf("%.2f ", Double.valueOf(d));
}
// expected otuput is 0.30 0.50 0.10 1.00 0.65
System.out.println();
System.out.println("All done.");
}
static public double[] normalizeValuesByHighest(final double[] pInitialValues) {
if (pInitialValues == null) throw new IllegalArgumentException("Invalid double[] given!");
if (pInitialValues.length < 1) throw new IllegalArgumentException("double[] given contains no elements!");
// detect valid max value
double tempMaxValue = -Double.MAX_VALUE;
boolean hasValues = false;
for (final double d : pInitialValues) {
if (Double.isNaN(d)) continue;
tempMaxValue = Math.max(tempMaxValue, d);
hasValues = true;
}
if (!hasValues) throw new IllegalArgumentException("double[] given contains no valid elements, only NaNs!");
// create return array
final double maxValue = tempMaxValue; // final from here on
final double[] ret = new double[pInitialValues.length];
for (int i = 0; i < pInitialValues.length; i++) {
ret[i] = pInitialValues[i] / maxValue; // NaN will stay NaN
}
return ret;
}
}
Output:
Adjusted values:
0,30 0,50 0,10 1,00 0,65
All done.
When I use numbers such as the one store in decimal the output just starts showing weird answers
this is my code
public static void main(String[] args) {
long decimal =444444;
long count = 0;
long a = 0;
long b = 0;
while(decimal != 0)
{
a = decimal%2;
b += a* Math.pow(10, count);
count++;
decimal = decimal/2;
}
System.out.print(b);
}
this is the output that it prints 1101100100000011136 when the right output should be 1101100100000011100 for decimal 444444
now when I input 123456 it prints 11110001001000000 which is right
I must use long for this and without using strings so that is the code that I'm using but I can't find a way to fix it since mathematically it seems to work.
edit: the goal of the code is to display the binary representation of the decimal in called "decimal" without using string or arrays
It because the maximum number a long can hold is 9,223,372,036,854,775,807(I get this from Long.MAX_VALUE) and your b after loop for a while it exceeds that maximum value and cannot hold correct value anymore. there for you will have some unexpected result. So with long type, I'm afraid that your function only corrects with a small value.
UPDATE
Since you don't use array or String to hold the binary result, you can use BigInteger to store the value of binary, it can hold more than long.
As what the other answers has pointed out, you can generate the output into a string instead as follows.
long decimal = 444444;
long a = 0;
String result = "";
while ( decimal != 0 )
{
a = decimal % 2;
result = Long.toString( a ) + result;
decimal = decimal / 2;
}
System.out.print( result );
Edit: This has to do with how computers handle floating point operations, a fact that every programmer faces once in a lifetime. I didn't understand this correctly when I asked the question.
I know the simplest way to start dealing with this would be:
val floatNumber: Float = 123.456f
val decimalPart = floatNumber - floatNumber.toInt() //This would be 0.456 (I don't care about precision as this is not the main objective of my question)
Now in a real world with a pen and a piece of paper, if I want to "convert" the decimal part 0.456 to integer, I just need to multiply 0.456 * 1000, and I get the desired result, which is 456 (an integer number).
Many proposed solutions suggest splitting the number as string and extracting the decimal part this way, but I need the solution to be obtained mathematically, not using strings.
Given a number, with an unknown number of decimals (convert to string and counting chars after . or , is not acceptable), I need to "extract" it's decimal part as an integer using only math.
Read questions like this with no luck:
How to get the decimal part of a float?
How to extract fractional digits of double/BigDecimal
If someone knows a kotlin language solution, it would be great. I will post this question also on the math platform just in case.
How do I get whole and fractional parts from double in JSP/Java?
Update:
Is there a "mathematical" way to "calculate" how many decimals a number has? (It is obvious when you convert to string and count the chars, but I need to avoid using strings) It would be great cause calculating: decimal (0.456) * 10 * number of decimals(3) will produce the desired result.
Update 2
This is not my use-case, but I guess it will clarify the idea:
Suppose you want to calculate a constant(such as PI), and want to return an integer with at most 50 digits of the decimal part of the constant. The constant doesn't have to be necessarily infinite (can be for example 0.5, in which case "5" will be returned)
I would just multiply the fractional number by 10 (or move the decimal point to the right) until it has no fractional part left:
public static long fractionalDigitsLong(BigDecimal value) {
BigDecimal fractional = value.remainder(BigDecimal.ONE);
long digits;
do {
fractional = fractional.movePointRight(1); // or multiply(BigDecimal.TEN)
digits = fractional.longValue();
} while (fractional.compareTo(BigDecimal.valueOf(digits)) != 0);
return digits;
}
Note 1: using BigDecimal to avoid floating point precision problems
Note 2: using compareTo since equals also compares the scale ("0.0" not equals "0.00")
(sure the BigDecimal already knows the size of the fractional part, just the value returned by scale())
Complement:
If using BigDecimal the whole problem can be compressed to:
public static BigInteger fractionalDigits(BigDecimal value) {
return value.remainder(BigDecimal.ONE).stripTrailingZeros().unscaledValue();
}
stripping zeros can be suppressed if desired
I am not sure if it counts against you on this specific problem if you use some String converters with a method(). That is one way to get the proper answer. I know that you stated you couldn't use String, but would you be able to use Strings within a Custom made method? That could get you the answer that you need with precision. Here is the class that could help us convert the number:
class NumConvert{
String theNum;
public NumConvert(String theNum) {
this.theNum = theNum;
}
public int convert() {
String a = String.valueOf(theNum);
String[] b = a.split("\\.");
String b2 = b[1];
int zeros = b2.length();
String num = "1";
for(int x = 0; x < zeros; x++) {
num += "0";
}
float c = Float.parseFloat(theNum);
int multiply = Integer.parseInt(num);
float answer = c - (int)c;
int integerForm = (int)(answer * multiply);
return integerForm;
}
}
Then within your main class:
public class ChapterOneBasics {
public static void main(String[] args) throws java.io.IOException{
NumConvert n = new NumConvert("123.456");
NumConvert q = new NumConvert("123.45600128");
System.out.println(q.convert());
System.out.println(n.convert());
}
}
output:
45600128
456
Float or Double are imprecise, just an approximation - without precision. Hence 12.345 is somewhere between 12.3449... and 12.3450... .
This means that 12.340 cannot be distinghuished from 12.34. The "decimal part" would be 34 divided by 100.
Also 12.01 would have a "decimal part" 1 divided by 100, and too 12.1 would have 1 divided by 10.
So a complete algorith would be (using java):
int[] decimalsAndDivider(double x) {
int decimalPart = 0;
int divider = 1;
final double EPS = 0.001;
for (;;) {
double error = x - (int)x;
if (-EPS < error && error < EPS) {
break;
}
x *= 10;
decimalPart = 10 * decimalPart + ((int)(x + EPS) % 10);
divider *= 10;
}
return new int[] { decimalPart, divider };
}
I posted the below solution yesterday after testing it for a while, and later found that it does not always work due to problems regarding precision of floats, doubles and bigdecimals. My conclusion is that this problem is unsolvable if you want infinite precision:
So I re-post the code just for reference:
fun getDecimalCounter(d: Double): Int {
var temp = d
var tempInt = Math.floor(d)
var counter = 0
while ((temp - tempInt) > 0.0 ) {
temp *= 10
tempInt = Math.floor(temp)
counter++
}
return counter
}
fun main(args: Array <String> ) {
var d = 3.14159
if (d < 0) d = -d
val decimalCounter = getDecimalCounter(d)
val decimalPart = (d - Math.floor(d))
var decimalPartInt = Math.round(decimalPart * 10.0.pow(decimalCounter))
while (decimalPartInt % 10 == 0L) {
decimalPartInt /= 10
}
println(decimalPartInt)
}
I dropped floats because of lesser precision and used doubles.
The final rounding is also necessary due to precision.
Imagine that I have 4,81 (double), how can i get the figures after the comma?
I want to receive 8 as a Integer and 1 as another.
Thanks
Doubles are tricky to work with when you're interested in decimal properties such as the decimal digits of the fractional part.
I suggest you let String.valueOf do the transformation to decimal digits and work with the resulting string.
double d = 4.81;
String s = String.valueOf(d);
for (int i = s.indexOf(".") + 1; i < s.length(); i++) {
int digit = Character.getNumericValue(s.charAt(i));
System.out.println(digit);
}
Output:
8
1
You can always make this kind of loop:
double number = 4,81;
while (condition) {
number *= 10;
int nextNumber = Math.floor(number) % 10;
}
I am having trouble with floating points. A the double . 56 in Java, for example, might actually be stored as .56000...1.
I am trying to convert a decimal to a fraction. I tried to do this using continued fractions
Continuous Fractions
but my answers using that method were inaccurate due to how to computer stored and rounded decimals.
I tried an alternative method:
public static Rational rationalize(double a){
if(a>= 1){
//throw some exception
}
String copOut = Double.toString(a);
int counter = 0;
System.out.println(a);
while(a%1 != 0 && counter < copOut.length() - 2){
a *= 10;
counter++;
}
long deno = (long)Math.pow(10,counter);//sets the denominator
Rational frac = new Rational((long)a,deno)//the unsimplified rational number
long gcd = frac.gcd();
long fnum = frac.getNumer();//gets the numerator
long fden = frac.getDenom();//gets the denominator
frac = new Rational(fnum/gcd, fden/gcd);
return frac;
}
I am using the string to find the length of the decimal to determine how many time I should multiply by 10. I later truncate the decimal. This gets me the right answer, but it does not feel like the right approach?
Can someone suggest the 'correct' way to do this?
Actually you are doing great.. But this will fail if the Input is something about 11.56. Here you need to to do copOut.length() - 3.
To make it dynamic use String#split()
String decLength = copOut.split("\\.")[1]; //this will result "56" (Actual string after decimal)
Now you just need to do only
while(a%1 != 0 && counter < decLength.length()){
a *= 10;
counter++;
}
If you want to remove the loop then use
long d = (long)Math.pow(10,decLength.length());
a=a*d;