Printf in Java with variable spaces before the output - java

With printf I can decide how many space characters should be before the variable i that I want to print. In the example below, it is 10. Is it possible to have there a variable instead of the number 10? So that the spaces characters depend on the value of a variable?
System.out.printf("%10d" , i);

The format string is still a string, so assuming a width variable System.out.printf("%" + width + "d", x); does the trick.
So for example
var width = 10; var x = 123;
System.out.printf("%" + width + "d", x);
prints 123 (7 leading spaces + 3 digits = 10), while
var width = 3; var x = 123;
System.out.printf("%" + width + "d", x);
prints 123

Define a lambda to create the desired width and then call that prior to printing the value.
Function<Integer, String> format = width-> "%%%dd\n".formatted(width);
int x = 4567;
System.out.printf(format.apply(10),x);
System.out.printf(format.apply(5),x);
// or create it once for multiple printf calls.
String form = format.apply(3);
System.out.printf(form, 2);
System.out.printf(form, 4);
prints
4567
4567
2
4
%%%dd - the first % escapes the second so on the last %d formats the width value.
then that format string is returned and used to format the supplied argument in the printf statement

Related

How would I add two int that are in the same array to each other and convert them into an int. In the Luhn Algorithm

I am trying to add two parts of an array together to go into an int value. I am using Luhn algorithm to figure out of a credit card is a valid credit card. We are only using 6 digit credit card's just to make sure no one enter's a real credit card number. The part I am confused on is when I go to split a number that is above 10 and add it together. Example if the algorithm was to give me 12 I would need to separate it into 1 and 2 and then add them together to equal 3. I believe I am splitting it currently in the code but when I go to add them together I get some number that makes no since. here is a section of the code with some notes about it.
I have printed out numbers in certain places to show myself what is going on in certain places. I have also added in some comments that say that either the number that is printed out is what is expected, and some comments for when there isn't something I expected
int[] cardNumber = new int[]{ 1,2,3,4,5,5};
int doubleVariablesum = 0;
int singleVariablesum = 0;
int totalSum = 0;
int cutOffVar = 0;
String temp2;
for (int i = cardNumber.length - 1; i >= 0;) {
int tempSum = 0;
int temp = cardNumber[i];
temp = temp * 2;
System.out.println("This is the temp at temp * 2: " + temp);
temp2 = Integer.toString(temp);
if (temp2.length() == 1) {
System.out.println("Temp2 char 0: "+ temp2.charAt(0));
// this prints out the correct number
// Example: if there number should be 4 it will print 4
tempSum = temp2.charAt(0);
System.out.println("This is tempSum == 1: " + tempSum);
// when this goes to add temp2.charAt(0) which should be 4 it prints out //something like 56
} else {
System.out.println("TEMP2 char 0 and char 1: " + temp2.charAt(0) + " " + temp2.charAt(1));
// this prints out the correct number successfully spited
tempSum = temp2.charAt(0) + temp2.charAt(1);
System.out.println("This is tempSum != 1: " + tempSum);
// but here it when I try to add them together it is giving me something
// like 97 which doesn't make since for the numbers I am giving it
}
doubleVariablesum = tempSum + doubleVariablesum;
System.out.println("This is the Double variable: " + doubleVariablesum);
System.out.println();
i = i - 2;
}
Since you are converting the number to a string to split the integer, and then trying to add them back together. You're essentially adding the two characters numerical values together which is giving you that odd number. You would need to convert it back to an integer, which you can do by using
Integer.parseInt(String.valueOf(temp2.charAt(0)))
When adding char symbols '0' and '1' their ASCII values are added - not numbers 0 and 1.
It is possible to use method Character::getNumericValue or just subtract '0' when converting digit symbol to int.
However, it is also possible to calculate sum of digits in a 2-digit number without any conversion to String and char manipulation like this:
int sum2digits = sum / 10 + sum % 10; // sum / 10 always returns 1 if sum is a total of 2 digits
Seems like charAt() type casts into integer value, but the ascii one. Hence for the characters '0' and '1', the numbers 48 and 49 are returned resulting in a sum of 97. To fix this, you could just assign temp2 to (temp / 10) + (temp % 10). Which actually splits a two digit integer and adds their sum.
You need to be aware of the following when dealing with char and String
Assigning the result of charAt(index) to an int will assign the ASCII value and not the actual integer value. To get the actual value you need to String.valueOf(temp2.charAt(0)).
The result of concatenating chars is the sum of the ASCII values.
eg if char c = '1'; System.out.println(c + c); will print "98" not "11".
However System.out.println("" + c + c); will print "11". Note the "" will force String concatenation.

Replace all non digits with a restriction

I'm trying to extract the first number from expressions:
Here's my code for while:
String[] strArray = input.split("\\+ ");
double[] numbers = getNumbersFromString();
public static double[] getNumbersFromString() {
double[] numbers = new double[strArray.length];
for (int i = 0; i < strArray.length; i++) {
numbers[i] = Double.parseDouble(strArray[i].replaceAll("\\D", ""));
}
return numbers;
}
Inputs and their expected outputs:
Z = 4x1 + 3x2 + 6x3 // 4 3 6
Z = 24x1 + 33x2 + 68x3 // 24 33 68
Z = 412x1 + 309x2 + 612x3 // 412 309 612
Z = 4329x1 + 3901x2 + 6716x3 // 4329 3901 6716
Actually, it's removing but it retrieves besides the first number, the second also. Eg.(In the first case): // 41 32 63, while it should be only // 4 3 6.
I could do something like "\\w = |x\\d", "", but it will only work for this specific case, I want a more general thing.
Thanks in advance.
Edit:
I got the following answer for the original question:
String input = "Z = 4329x1 + 3901x22 + 6716x3";
input = input.replaceAll("^\\D+", "");
double[] numbers = Pattern.compile("x\\d+\\D*")
.splitAsStream(input)
.mapToDouble(Double::parseDouble)
.toArray();
But now appeared a new thing to be done. Inputs that has no numbers before the x1/x2/x3.. or any kind of this" should be replaced by the number "1".
Some inputs and their respective expected outputs:
Z = x11 + x2 + x90 // 1 1 1
Z = 2x1 + 2x4 + x9 // 2 2 1
By the way, I have made this regex: (?<!\d)x\d+.
Then I modified the code to:
return Pattern.compile("x\\d+\\D*")
.splitAsStream(input.replaceAll("(?<!\\d)x\\d+","1").replaceAll("^\\D+", ""))
.mapToDouble(Double::parseDouble)
.toArray();
But it's returning me `java.lang.NumberFormatException: For input string: "1 + 3".
PS: it should work for either the old and new case.
This should work as required:
String s = "Z = 4329x1 + 3901x22 + 6716x3";
String[] split = s.replaceAll("^\\D+", "").split("x\\d+\\D*");
System.out.println(Arrays.toString(split)); //[4329, 3901, 6716]
With streams you could do something like this to obtain your array of doubles:
String input = "Z = 4329x1 + 3901x22 + 6716x3";
input = input.replaceAll("^\\D+", "");
double[] numbers = Pattern.compile("x\\d+\\D*")
.splitAsStream(input)
.mapToDouble(Double::parseDouble)
.toArray();
EDIT
To also accept expressions such as x1 + x2, you can default to 1 when the string returned by split is empty (and amend the regex slightly):
String input = "Z = x1 + x2 + 6716x3";
input = input.replaceAll("^[^x\\d]+", "");
double[] numbers = Pattern.compile("x\\d+[^x\\d]*")
.splitAsStream(input)
.mapToDouble(s -> s.isEmpty() ? 1d : Double.parseDouble(s))
.toArray();
RE-EDIT
Add the missing 1 before the x manually:
String input = "Z = x1 + x2 + 6716x3 + x4";
input = input.replace(" x", " 1x")
.replaceAll("^[^x\\d]+", "");
double[] numbers = Pattern.compile("x\\d+[^x\\d]*")
.splitAsStream(input)
.mapToDouble(Double::parseDouble)
.toArray();
You could do the whole grabbing in a single regex (per row which I assume from your example what you're interested in) -
(?:=|\+)\s*(\d+)
It matches either a = or a +, skipping any spaces and then captures the number. Make it global and it'll capture the entire row. The result will be in the capture group array. (Don't speak java well enough to tell you exactly how from the top of my head).
Check it here at regex101. (Note - sample shows all the rows at once - you'd have to do them one by one.)
Since you pattern is a number followed by an x, using positive lookahead like this will work.
Regex: \d+(?=x)
Explanation:
(?=x) looks ahead and checks if x is present. If yes then \d+ is matched.
Regex101 Demo
Note: Use double escape \\d if necessary.

BigDecimal formatting [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'd like to format a BigDecimal in Java to 8 Characters (including the seperator), rounding HALF-UP.
Some examples:
12345.6789 -> "12345.68"
123 -> " 123.0"
0.12345678 -> "0.123457"
1.5 -> " 1.5"
0.0045 -> " 0.0045"
12 -> " 12.0"
The result must have leading spaces to fill up to 8 characters.
What's the easiest way?
I'm pretty sure this is not the best way, but it's one way.
First note that if your numbers have more than six digits before the period, or more generally more than width - 2 digits before the period, your format with .0 will not work anymore.
String.format() uses half up as a rounding method, so you can use it as a first step to get your output to eight characters.
BigDecimal b = new BigDecimal(0.0045);
String format = "%8f";
String str = String.format(format, b);
Output:
12345.678900
123.000000
0.123457
1.500000
0.004500
12.000000
123456.000000
By default String.format() uses a precision of 6 for BigDecimal. To get your custom precision, you need to know how many digits are before the period and substract this number (+ 1 for the period itself) from the total width.
width - digits - 1
To get the number of digits you can simply check if (number % radix) == number applies for radix = 10, 100, 1000, ... As soon as it fits you know the number of digits.
public static int digitsBeforePeriod(BigDecimal b) {
int number = b.intValue();
int radix = 10;
int digits = 1;
while((number % radix) != number) {
radix *= 10;
++digits;
}
return digits;
}
So the next step is to modify the format:
BigDecimal b = new BigDecimal(0.0045);
int digits = digitsBeforePeriod(b);
String format = "%8." + (8 - digits - 1) + "f";
String str = String.format(format, b);
Output:
12345.68
123.0000
0.123457
1.500000
0.004500
12.00000
123456.0
Still there are lots of 0s, but at least the rounding is correct now. Now you specify that if a number is round to an integer, you want to print it with a .0 suffix, otherwise without.
To achieve this there might also exist clever formats, I didn't think any further though. The naive way to do this is simply:
while(str.endsWith("0") && !str.endsWith(".0")) {
str = str.substring(0, str.length()-1);
}
This removes the last character of the string until it either doesn't end on 0 at all or ends with .0.
Now the numbers will have the correct format, but are not aligned correctly:
12345.68
123.0
0.123457
1.5
0.0045
12.0
123456.0
To align them, just use the String.format() again.
str = String.format("%" + width + "s", str);
Output:
12345.68
123.0
0.123457
1.5
0.0045
12.0
123456.0
In the context this looks like the following. Note that I included a check wether or not the number can be formatted that way - if not, it will print Invalid. You can of course also just print the number, I just wanted to show the limitations of that format.
public static String trimToWidth(BigDecimal b, int width) {
String str = "Invalid";
int digits = digitsBeforePeriod(b);
// -2 for period and 0
if(digits <= width - 2) {
// use width and (width - digits - 1) as precision (-1 for period)
String format = "%" + width + "." + (width - digits - 1) + "f";
// rounds half-up
str = String.format(format, b);
// trim trailing 0s, unless it's .0
while(str.endsWith("0") && !str.endsWith(".0")) {
str = str.substring(0, str.length()-1);
}
}
// add spaces in front
str = String.format("%" + width + "s", str);
return str;
}
public static int digitsBeforePeriod(BigDecimal b) {
int number = b.intValue();
int radix = 10;
int d = 1;
while((number % radix) != number) {
radix *= 10;
++d;
}
return d;
}
public static void main(String[] args) {
double[] values = new double[] {
12345.6789, 123, 0.12345678,
1.5, 0.0045, 12, 123456, 1234567
};
BigDecimal[] bigs = new BigDecimal[values.length];
for(int i = 0; i < bigs.length; ++i) {
bigs[i] = new BigDecimal(values[i]);
System.out.println(trimToWidth(bigs[i], 8));
}
}

Why is myArrayList.size(); producing incorrect/gigantic numbers?

Basically, I'm trying to write a program that converts a number from base 2 to base 10. What I tried doing was translating the process listed on this website under the "Doubling method" into a for loop, but for some reason the numbers I'm getting are way to big.
The basic formula is (2 * previousTotal) + (currentDigit of the ArrayList that holds the user's inputted binary number) = previousTotal.
So for 1011001 in binary, the math would be:
(0 x 2) + 1 = 1
(1 x 2) + 0 = 2
(2 x 2) + 1 = 5
(5 x 2) + 1 = 11
(11x 2) + 0 = 22
(22 x 2) + 0 = 44
(44 x 2) + 1 = 89
The console however, prints out 6185 as the result. I'm thinking it might have something to do with me using an ArrayList of characters, but the charWhole.size() returns 7, which is how many digits are in the user's binary number. As soon as I do charsWhole.get(w); however, I start getting big numbers such as 49. I'd really appreciate some help!
I wrote out this loop, and according to some print statements that I placed throughout the code and my variable addThis seems to be where the problem is. The console prints out a final total of 6185, when 1011001 in base 10 is actually 89.
public static void backto2(){
System.out.println("What base are you coming from?");
Scanner backToB10 = new Scanner(System.in);
int bringMeBack = backToB10.nextInt();
//whole
System.out.println("Please enter the whole number part of your number.");
Scanner eachDigit = new Scanner(System.in);
String theirNumber = eachDigit.nextLine();
String str = theirNumber;
ArrayList<Character> charsWhole = new ArrayList<Character>();
for (char testt : str.toCharArray()) {
charsWhole.add(testt);
}
System.out.println(theirNumber); // User's number
System.out.println(charsWhole); // User's number separated into elements of an ArrayList
System.out.println(charsWhole.size()); // Gets size of arrayList, comes out as 7 which seems fine.
int previousTotal = 0, addThis = 0, q =0;
for( int w = 0; w < charsWhole.size(); w ++) {
addThis = charsWhole.get(w); //current digit of arraylist PROBLEM
q = previousTotal *2;
previousTotal = q + addThis; // previous total gets updated
System.out.println(q);
System.out.println(addThis);
System.out.println(q + " and " + addThis + "equals " + previousTotal);
}
System.out.println(previousTotal);
You are attempting to add a character to an integer. The implicit conversion uses the ASCII value of the character, so that '1' gets converted to 49, not 1, because 49 is the code for the character '1'. Subtract '0' to get the actual integer value.
addThis = charsWhole.get(w) - '0';
This works because the digits 0-9 are represented in ASCII as the codes 48-57, so in effect you will, for '1', subtract 49 - 48 to get 1.
You'll still have to handle cases when the character is outside the range of allowable characters.
EDIT
Java uses Unicode, but for the purposes of the codes for the digits 0-9, the codes are the same (48 thru 57, or 0x30 thru 0x39) in both ASCII and Unicode.
The problem is that you're using the chars rather than the number value they represent. In the line
addThis = charsWhole.get(w);
the value of addThis is the ascii value of the character. For '0', this is 48. Use this instead:
addThis = Integer.parseInt(charsWhole.get(w));
Another suggestion to solve the same problem:
addThis = charsWhole.getNumericValue(w);
See here for more information.

Java Random Print

I generate a random number between 0-99 using this :
int num2= (int)(Math.random() * ((99) + 1));
When the number is below 10 I want it to print with a 0num2
So if the number is 9 it would be 09.
How can I get it to print this?
You can use the format() method:
System.out.format("%02d%n", num2);
%02d prints the argument as a number with width 2, padded with 0's
%n gives you a newline
System.out.println((num2 < 10 ? "0" : "") + num2);
One liner :-)
String str;
if (num2 < 10) str = "0" + num2;
else str = "" + num2;
System.out.println("Value is: " + str);
Have a look at PrintStream.format, which will allow you to print using specified widths and padding characters.
System.out is a PrintStream, so you can use System.out.format in place of println.
Your case is pretty simple, look over the syntax for the format string:
System.out.format("%02d", num2);
Here 2 is the minimum width, and the 0 specifies that the result be padded with zeros, if the width of the result is less than 2.
You can use the approach of removing an extra digit instead.
System.out.println(("" + (int)(Math.random()*100 + 100)).substring(1));
or to use the String format.
String s = String.format("%02d", (int)(Math.random()*100));
or
System.out.printf("%02d", (int)(Math.random()*100));
I would generally use the last option as it allows you to combine other strings and print them.

Categories

Resources