I just started learning Java and I'm doing a little program to convert a decimal number into binary numbers using only while loops.
The results were reversed, therefore I'm using a method to reverse the string. But the reverse method does not work for me. Could anyone help me, please?
The following is my code:
import java.util.Scanner;
public class NumberConversion {
public static void main(String[] args) {
Scanner getnumber = new Scanner(System.in);
System.out.print("Enter number: ");
int originalnum = getnumber.nextInt();
int remainder;
String binary_temp;
if (originalnum % 2 != 0) {
while (originalnum > 0) {
remainder = originalnum % 2;
originalnum /= 2;
binary_temp = String.valueOf(remainder);
String binarynum = new StringBuffer(binary_temp).reverse().toString();
System.out.print(binarynum);
}
}
else if (originalnum % 2 == 0) {
while (originalnum > 0) {
originalnum /= 2;
remainder = originalnum % 2;
binary_temp = String.valueOf(remainder);
String binarynum = new StringBuffer(binary_temp).reverse().toString();
System.out.print(binarynum);
}
}
}
}
But the reverse method does not work for me.
That's because you are reversing a string that contains a single digit. If you run your code through a debugger, you will discover that. Every programmer needs to know how to debug code, including code written by other people.
You need to build up the string of binary digits using a single StringBuffer and only after the while loop you reverse the string.
Also, from the code in your question:
if (originalnum % 2 != 0) {
If the above condition is not true, then originalnum % 2 must be zero, hence not need for if-else, i.e. (also from the code in your question):
else if (originalnum % 2 == 0) {
You just need else by itself.
However, you don't need that if-else at all. You just need a single while loop and a single StringBuffer. Actually, for a single-threaded program – such as yours – it is better to use StringBuilder. And rather than creating a new StringBuffer and reversing it on each iteration of the while loop, you can simply insert the [binary] digit.
(More notes after the code.)
import java.util.Scanner;
public class NumberConversion {
public static void main(String[] args) {
Scanner getnumber = new Scanner(System.in);
System.out.print("Enter number: ");
int originalnum = getnumber.nextInt();
originalnum = Math.abs(originalnum);
StringBuilder sb = new StringBuilder();
if (originalnum == 0) {
sb.append('0');
}
else {
while (originalnum > 0) {
int remainder = originalnum % 2;
sb.insert(0, remainder);
originalnum /= 2;
}
}
System.out.println(sb);
}
}
I assume that you only want to handle positive numbers, hence the call to method abs.
The while loop does not handle the case where originalnum is 0 (zero), hence the if (originalnum == 0)
Have you seen Oracle's Java tutorials?
I also recommend the book Java by Comparison by Simon Harrer, Jörg Lenhard & Linus Dietz.
you can use for loop and server your string , here is example
public class StringFormatter {
public static String reverseString(String str){
char ch[]=str.toCharArray();
String rev="";
for(int i=ch.length-1;i>=0;i--){
rev+=ch[i];
}
return rev;
}
}
You can use one line to reverse the string
String reversedString = (new StringBuilder().append(oldString).reverse().toString());
Related
Hello guys,
I would like to share with you my problem. I am practicing recursive methods and i have noticed somewhere one exercise. The exercise is about making the recursive method which adds a 0 to every even digit. If someone has some idea, it would be great if you share here.
the code would be something like this :
public static String adding0AfterEvenNumber(int number) {
String s = String.valueOf(number);
String result;
if (number < 10 && number % 2 == 0) {
return s + 0;
}
}
I am missing the main part of the code but i really do not have an idea how to create it. Thanks in advance
consider this code (comments in line)
// somewhere to store the result
static StringBuilder result = new StringBuilder();
public static void main(String [] args) {
// starting string
String s = "1234567";
// or as
//String s = Integer.toString(1234567);
// call with full string
recurse (s);
// print result
System.out.println("result : " + result.toString());
}
private static void recurse(String s) {
// take first char and add to result
String c = s.substring(0,1);
result.append(c);
// see if even, note no error checking for is a number
if (Integer.parseInt(c) % 2 == 0) {
result.append("0");
}
// then if still has content then strip off first char and call again
if (s.length() > 1)
recurse(s.substring(1));
}
output
result : 1203405607
You would recurse something like this:
public static String adding0AfterEvenNumber(int number) {
return ((number >= 10) ? adding0AfterEvenNumber(number / 10) : "") + String.valueOf(number % 10) + ((number % 2 == 0) ? "0" : "");
}
Try it here.
<script src="//repl.it/embed/JDEV/1.js"></script>
The first part is the terminal condition, appending nothing if there is a single digit number, else calling the recursion after removing the last digit:
(number > 10) ? adding0AfterEvenNumber(number / 10) : "")
The second part appends a zero to the last digit, if even:
String.valueOf(number % 10) + ((number % 2 == 0) ? "0" : "")
I understand that even digits are those digits with an even value not in an even position. The following function should return you a string with the value, although you could return an integer if you shift the head value as many digits as the tail has.
public String add0onEven(int number, int initPos, int endPos) {
if (initPos == endPos - 1) {
int digit = (number / (int) Math.pow(10, initPos)) % 10;
if (digit % 2 == 1) {
return digit + "0";
} else {
return "" + digit;
}
} else if (endPos - initPos < 1) {
return "";
} else {
int sepIdx = (endPos - initPos) / 2 + initPos;
String tail = add0onEven(number, initPos, sepIdx);
String head = add0onEven(number, sepIdx, endPos);
return head + tail;
}
}
You can call the method like this:
add0onEven(1234567, 0, 7)
The output obtained for this invocation:
10230450670
I believe this solution to be better than the substring ones for its lower impact on memory (No need to create a new string on each substring invocation). Besides, it follows a Divide and Conquer approach that suits better to recursivity.
I was working on a question that requires a concatenation of strings recursively and ran into a problem.
Question states that s(0) = 0, s(1) = 1, s(n) = s(n-1)s(n-2) for n >= 2, where s(n) is the concatenated string of the previous two strings.
Input will indicate how many instances of (n, k) pair will be input as the first integer, followed by each line containing a non-negative integer
n (0 <= n <= 60) and a positive integer k.
Output is supposed to be printing out the kth character of the concatenated string s(n), where k is less or equal to the number of characters in string s(n).
s(0) = 0
s(1) = 1
s(2) = 10
s(3) = 101
s(4) = 10110
s(5) = 10110101
and so on.
Sample input:
3
5 2
0 1
4 3
Output:
0
0
1
My code:
import java.util.*;
public class recursivestring {
public static String recursive(int n, int i, String str1, String str2){
if (i == n - 1)
return str1 + str2;
return recursive(n, i + 1 , str1 + str2, str1);
}
public static void main(String[] args) {
int lines, i, n, k;
String result;
Scanner input = new Scanner(System.in);
lines = input.nextInt();
for (i = 0; i < lines; i++) {
n = input.nextInt();
k = input.nextInt();
if (n == 0) {
result = "0";
} else if (n == 1) {
result = "1";
} else if (n == 2) {
result = "10";
} else {
result = recursive(n, 2, "10", "1");
}
System.out.println(result.charAt(k-1));
}
}
}
This is what I have so far, and it works for the given sample test case. It works for most cases but once n becomes large, I get this error
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Why is that happening and is there something wrong with my code?
Thank you!
The problem with your approach is that it creates too many throw-away strings. Each time you write
return str1 + str2;
a new String object is created. The number of such throw-away objects grows linearly with n, while their total length grows as O(n2).
You have two solutions to this problem:
Keep your program linear, and pass StringBuilder at the top level. Each recursive invocation would call append, rather than using operator + for concatenation.
Use Memoization - since the number of strings that you need to compute is small, storing the ones that you computed so far and re-using them should fix the problem.
A bigger issue with your problem limits is that its output cannot fit in a String: Java allows strings of up to 231 in length, while the output of your code for 60 is quite a bit longer - namely, 1,548,008,755,920 characters. While you should be able to save this output in a file, there is no way to store it as a String, with or without memoization.
Since you're doing this in Java and not in an FP language with tail call optimization, two things are wrong: recursion and string concatenation. In Java you would to iteration and string building with a mutable builder.
Specifically, your recursive function retains all the interim string you produce on your way to the full string. That's O(n2) memory usage.
Well, to be honest this looks like fibonacci to me so me approach looks a little like that...
public static void main(String[] args) {
for (int i = 0; i < 6; i++) {
System.out.println(stringbonacci(i));
}
}
private static String stringbonacci(int i) {
if (i == 0) {
return "0";
}
if (i == 1) {
return "1";
} else {
return stringbonacci(i - 1) + stringbonacci(i - 2);
}
}
and the result looks like:
0
1
10
101
10110
10110101
I highly recommend caching the result of each method call so that you don't have to re-calculate everything more than once. Will greatly improve your performance at the cost of a small bit of heap. Something like... this?
public class RecursiveString {
private static final Map<Integer, String> cache = new HashMap<>();
static {
cache.put(0, "0");
cache.put(1, "1");
}
public static String generateString(Integer i) {
if (i < 0) return generateString(0); // or something... avoid negatives.
if (cache.get(i) != null) return cache.get(i); // cache hit.
String generated = String.format("%s%s",
generateString(i-1), generateString(i-2));
cache.put(i, generated);
return generated;
}
}
Note that on a 2G heap, generateString works up through i=40 on my machine, simply due to the length of the resulting string. The string's length is going to be 2*fib(i) bytes in size, so your memory requirement is going to explode pretty quickly once you start hitting those indexes.
Same idea as the answer with the map (store the intermediate string, don't recompute), but using an array instead.
This could be optimized a little more by reading all the lines, then finding the maximum n value, thereby storing only one array, then looping back over the (n, k) pairs.
import java.util.Scanner;
public class BinaryConcat {
private String[] dict;
public BinaryConcat(int n) {
if (n < 0) throw new IllegalArgumentException();
dict = new String[2 + n]; // Have 2 base cases
dict[0] = "0";
dict[1] = "1";
}
public String getValue(int n) {
if (n < 0) throw new IllegalArgumentException();
if (n <= 1) return dict[n];
if (dict[n] == null || dict[n].isEmpty()) {
dict[n] = String.format("%s%s", getValue(n - 1), getValue(n - 2));
}
return dict[n];
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int lines = input.nextInt();
input.nextLine(); // consume linefeed
for (int i = 0; i < lines; i++) {
String line = input.nextLine();
String[] nk = line.split(" ");
int n = Integer.parseInt(nk[0]);
int k = Integer.parseInt(nk[1]);
String value = new BinaryConcat(n).getValue(n);
System.out.println(value.charAt(k - 1));
}
}
}
Sample run
(same input and output as expected)
A sample input of 12345 should return 12,345. I have it figured out i think. Only problem is the string I get is reversed (543,21). Now i know there's ways to reverse a string pretty easily but that's more complexity to the running time so I was wondering if there was a straightforward way to do it within the auxiliary itself?
public void print(int n){
String number = Integer.toString(n);
StringBuilder answer = new StringBuilder();
if(number.length() > 3){ //Only worry about adding commas if its more than three digits
printAux(number, answer, 1, number.length()-1);
System.out.println(answer);
}
}
private void printAux(String s, StringBuilder answer, int count, int index){
if(index < 0){
return;
}
else{
//If the counter is at the 4th index meaning it has passed three digits
if(count%3 == 1 && count > 3){
answer.append(",");
index = index + 1;
count = 0;
}
else{
answer.append(s.charAt(index));
}
printAux(s, answer, count + 1, index - 1);
}
}
Something simpler
public static void print(String s) {
out.print(s.charAt(0));
if (s.length() == 1) out.print("\n");
else {
if (((s.length()-1) % 3) == 0) out.print(",");
print(s.substring(1));
}
}
Explanation:
always print the 1st character
if there is no more character, print CR
if there is at least one character to process, check if the length of what to process is a multiple of 3, if yes print a ","
and call recursively print with the string minus the 1st character
You can can use StringBuilder.reverse() to reverse a String in one line like
String str = "abc";
str = new StringBuilder(str).reverse().toString();
But you could also use printf1. Something like,
public static void print(int n) {
System.out.printf("%,d%n", n);
}
public static void main(String[] args) {
int num = 123456789;
print(num);
}
Output is (as requested)
123,456,789
1See also The Java Tutorials - Formatting Numeric Print Output for more options.
You can use the following DecimalFormat to get the job done.
String number = "1000500000.574";
double amount = Double.parseDouble(number);
DecimalFormat formatter = new DecimalFormat("#,###.00");
System.out.println(formatter.format(amount));
In my program I need to insert - between two odd numbers and * between even numbers and ignore if there is 0. For example:
Input = 99946 Output = 9-9-94*6
Input = 56647304 Output = 56*6*47-304
Method getDigits() places the digits of the entered number into array cells. Method insertDashesAsteriks() returns properly concatenated String.
But when I run my program with the following example:
Please enter the numbers so they could be rearranged:
222234411110000
Exception in thread "main" java.util.InputMismatchException: For input string: "222234411110000"
at java.util.Scanner.nextInt(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at DashInsert2.main(DashInsert2.java:9)
then I'm getting InputMismatchException. Why am I getting the error?
import java.util.Scanner;
public class DashInsert2 {
public static void main(String[] args)
{
Scanner kbd = new Scanner(System.in);
System.out.println("Please enter the numbers so they could be rearranged: ");
int nums = kbd.nextInt();
int[] numArray = getDigits(nums);
System.out.println("The array representation of the numbers is \n");
System.out.println();
String result = insertDashesAsteriks(numArray);
System.out.println("The result is " + result);
}
public static int[] getDigits(int numbers)
{
int length = Integer.toString(numbers).length();
int[] temp = new int[length];
for(int i = 0; i < length; i++)
{
temp[i] = numbers % 10;
numbers = numbers / 10;
}
return temp;
}
public static String insertDashesAsteriks(int[] numArray)
{
String temp = "";
for(int i = 1; i < numArray.length; i++)
{
if(numArray[i] % 2 == 0 && numArray[i-1] % 2 ==0)
{
temp = numArray[i-1] + "*" + numArray[i] + "*";
}
else if(numArray[i] == 0 || numArray[i-1] == 0)
{
temp = numArray[i-1] + "" + numArray[i] + "";
}
else if(numArray[i] % 2 != 0 && numArray[i-1] % 2 != 0)
{
temp = numArray[i-1] + "-" + numArray[i] + "-";
}
}
return temp;
}
}
Maximum value for int is 2,147,483,647
You entered: 222,234,411,110,000
You'll need to treat the number as a string since the number you input is past the biggest possible 32 bit integer.
Try kbd.next().charAt(0); to parse it character by character instead.
First off, if you're reading in ints, you're limited to their range. That means numbers beyond about +/- two billion are out of the question. For handling larger number, you can move to larger data types (like long) or just handle strings, which have far less stringent limitations.
Once you are handling strings, there's a far simpler way (in terms of the code you have to write) to do this substitution using regular expressions:
public class Test {
static String morph(String s) {
String oldS;
do {
oldS = s;
s = s.replaceAll("([13579])([13579])", "$1-$2");
s = s.replaceAll("([2468])([2468])", "$1*$2");
} while (! s.equals(oldS));
return s;
}
public static void main(String args[]){
System.out.println(morph("99946"));
System.out.println(morph("56647304"));
System.out.println(morph("222234411110000"));
}
}
The morph function simply modifies the string with your substitution rules until it ceases to change. The output of the test harness (using the data you supplied) is:
9-9-94*6
56*6*47-304
2*2*2*234*41-1-1-10000
Now it may be that, if this is a classwork assignment, you're limited in the language facilities you can use. But, since you haven't mentioned that, and no coder in their right mind would (usually) choose a more difficult path, you should consider the use of the regular expression method. Code that is shorter is almost always less prone to bugs.
If you don't want to use regular expressions, you can still make your code relatively short and well structured, with something like:
// Helper functions for inserting characters.
static boolean is2468 (char ch) {
return (ch == '2' || ch == '4' || ch == '6' || ch == '8');
}
static boolean is13579 (char ch) {
return (ch == '1' || ch == '3' || ch == '5' || ch == '7' || ch == '9');
}
static String morph(String str) {
// Use efficient string builder for creating morphed string.
StringBuilder newStr = new StringBuilder();
// Last/current character, starting with '0' simplifies
// start condition.
char lastCh, ch = '0';
// Process every character in string.
for (int idx = 0; idx < str.length(); idx++) {
// Transfer previous current to last, get current.
lastCh = ch;
ch = str.charAt(idx);
// Put '-' between two odds, '*' between two non-zero evens.
if (is13579(lastCh) && is13579(ch))
newStr.append('-');
else if (is2468(lastCh) && is2468(ch))
newStr.append('*');
// Put character there regardless.
newStr.append(ch);
}
// Return string version of string builder.
return newStr.toString();
}
Hey I'm really trying to convert decimal int to binary int, without succes.
Please help me.
And I don't want to make it 'System.out.println()' becuase I've already done it.
THANKS!
`I need recursive function that gets decimal int and return binary int
public static void decToBin(int number) {
if(number == 0)
return ;
decToBin(number / 2);
System.out.print(number % 2);
}
That it what I've done...
When I'm trying to get string:
public static String decToBin(int number) {
if(number == 0)
return "";
return new Integer(number % 2).toString() + new Integer(decToBin(number / 2)).toString();
}
Error...
public static String decToBin(int number) {
if(number == 0)
return "";
return new Integer(number % 2).toString() + new Integer(decToBin(number / 2)).toString();
}
This approach has few flaws.
First you can't use "" as argument of new Integer("") because "" holds no value, so you will see NumberFormatException.
Other problem is order of generating result. number % 2 should be placed after result of decToBin(number / 2), just like you are doing it in your first example, where you are printing it after recursive decToBin call
decToBin(number / 2);
System.out.print(number % 2);
Lastly in your return statement you are creating new string, so to generate "100101" you will generate "" "1" "01" "101" 0101" "00101" and then finally "100101". To avoid it use StringBuilder and its append method.
This is a little old, but for the sake of reference and giving a correct answer, this is what you would need to do:
public static String dec2Bin(int num) {
String result = ((num % 2 == 0) ? "0" : "1");
if (num == 0 || num == 1) {
return result;
}
return dec2Bin(num/2) + result;
}
void intToBinary(int num) {
if (num < 2) {
System.out.print(num);
return;
} else {
intToBinary(num / 2);
intToBinary(num % 2);
}
}
import java.io.*;
class Binary{
public static void main(String args[])throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter the number:");
int n = Integer.parseInt(br.readLine());
System.out.print(Integer.toBinaryString(n));
}
}