I've got this bit of code here:
public class Project1 {
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
System.out.println("Input a binary number");
String binary = input.nextLine();
System.out.println(Conversion(binary));
}
public static int Conversion(String binary)
{
StringTokenizer st = new StringTokenizer(binary, " ");
int n = st.countTokens() - 1; // Used as the power number in b^n for conversion
int result = 0;
while(st.hasMoreTokens()){
int binaryInt = Integer.parseInt(st.nextToken());
result += binaryInt * (1 << n);
n--;
}
return result;
}
}
And it works beautifully... if the input has spaces in between the binary numbers. For example, if the input is 1 1 1 1, then it will rightfully return 15. Cool, but how do I change the tokenizer to not require spaces to split each digit? I tried doing StringTokenizer(binary, ""); and StringTokenizer(binary);, but neither properly split each digit into it's own token.
You will notice that, while StringTokenizer obviously only works with Strings, I've converted the Strings into ints inside my conversion method before returning the result.
# Tony I think you tried to add the ascii values of the digits here
for input value 10
for first run
int binaryInt = binary.char(i) ; so binaryInt would get the value = 49(aski value of char '1')
hence result = 49*2 = 98
in second run
result = 98 + 48 *1 = 146
following function will serve your purpose, for input String "1101" , it returns 13
public int getDecimal(String binaryString){
//binaryString = "1101";
int result = 0;
int n = binaryString.length()-1;
for(int i=0;i<binaryString.length();i++)
{
int num = binaryString.charAt(i);
if(num>=48 && num <=57){
result+=(num-48) * Math.pow(2, n) ;
n --;
}
}
return result;
}
}
How about something like this:
// remove everything that is not a digit
String digitsOnly = binary.replaceAll("[^\\d]","");
//iterate over every digit
for(char digit:digitsOnly.toCharArray()) {
int n = Character.getNumericValue(digit);
// do stuff...
}
If you get a string like "10011010", you don't need a tokenizer, you can just iterate over the string and use charAt:
for (int i = 0; i < s.length(); i++) {
char currentDigit = s.charAt(i);
// Do stuff with the digit
}
Related
I want to take the value of a ASCII value(Saved as a string) and convert it to the character to reveal a message. I tried this and it keeps throwing an index out of bound at the declaration of the int b.It also shows that str and b do not have a value
String value = "104 101 108 108 111";
char[] ch = new char[value.length()];
for (int i = 0; i < value.length(); i++) {
ch[i] = value.charAt(i);
}
System.out.println(ch.length);
String ans = "";
int i = 0;
while (i+2 < ch.length) {
int b= ch[i]+ch[i++]+ch[i+2];
String str = new Character((char) b).toString();
System.out.println(str);
System.out.println(b);
ans = ans+str;
i=i+3;
}
Using string split function
String value = "104 101 108 108 111";
String[] arrOfStr = value.split(" ");
String ans = "";
for(String str : arrOfStr) {
String str1 = Character.toString((char)Integer.parseInt(str));
ans += str1;
}
System.out.println(ans); // output: hello
We can switch the Imperative code to Declarative code using Java 8 Streams.
Key points to observe:
Declarative style is more readable and easy to write.
String Joiner is faster than simple String Concatenation.
No need to write an iterator.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String value = "104 101 108 108 111";
Arrays.stream(value.split(" ")) // Starting a stream of String[]
.mapToInt(Integer::parseInt) // mapping String to int
.mapToObj(Character::toChars) // finding ASCII char from int
.forEach(System.out::print); // printing each character
}
}
If you wish to store the result and then print it, this is how is done.
import java.util.Arrays;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
String value = "104 101 108 108 111";
String result = Arrays.stream(value.split(" ")) // Starting a stream of String[]
.mapToInt(Integer::parseInt) // mapping String to int
.mapToObj(Character::toChars) // finding ASCII char from int
.map(String::new) // convert char to String
.collect(Collectors.joining()); // combining individual result using String Joiner
System.out.println(result);
}
}
Comments to code:
There is a built-in method for for getting a char[] with the characters of a string, so the following two blocks of code are the same:
// Code from question
char[] ch = new char[value.length()];
for (int i = 0; i < value.length(); i++) {
ch[i] = value.charAt(i);
}
// Using built-in method
char[] ch = value.toCharArray();
It is better to use a for loop when increment a value while looping. The following two ways of writing the loop behave the same, but the for loop keeps the loop logic together:
// Code from question
int i = 0;
while (i+2 < ch.length) {
// some code here
i=i+3;
}
// Using for loop
for (int i = 0; i + 2 < ch.length; i=i+3) {
// some code here
}
The following line of code is entirely wrong:
int b= ch[i]+ch[i++]+ch[i+2];
i++ increments the value is i, but it is the value before the increment that is used in the expression, which means that if i = 0 before the line, the result is the same as this code:
int b = ch[0] + ch[0] + ch[2];
i = i + 1;
You need to replace i++ with i + 1, and realize that those are not the same.
Since you no longer increment the value of i by 1 in that statement, the loop much be changed from i=i+3 to i = i + 4, to correctly skip the spaces in the input.
The value of ch[i] is a char value, which is widened to an int value by the use of the + operator. The int value of a char is the Unicode Code Point value, which for your text is also the same as the ASCII code for the character.
This means that if i = 0, the expression would (after fixing issue #1) evaluate as:
int b = ch[0] + ch[1] + ch[2];
int b = `1` + `0` + `4`;
int b = 49 + 48 + 52;
int b = 149;
That matches the output from running the code is in question, where the second printed number is 149 (after fixing issue #1).
What you really wanted was to get the substring "104" and convert that to a number, then cast that ASCII code value to a char, like this:
String numberStr = value.substring(i, i + 3); // E.g. "104"
int number = Integer.parseInt(numberStr); // E.g. 104
String str = String.valueOf((char) number); // E.g. "h"
With that, you no longer need the char[], so the final code would be:
String value = "104 101 108 108 111";
String ans = "";
for (int i = 0; i + 2 < value.length(); i += 4) {
String numberStr = value.substring(i, i + 3);
int number = Integer.parseInt(numberStr);
String str = String.valueOf((char) number);
ans = ans + str;
}
System.out.println(ans);
Output
hello
I have a single line string of length n, which I want to split into maximum of 3 lines. Each line can have a maximum of 45 chars, after which I want to add a new-line char ("\n"). The 3rd line can have a maximum of 42 chars after which I need to include 3 dots (...) if the string goes beyond that, thus making the total characters in the 3rd line 45 as well.
The condition is that the new line character should not be added in the middle of a word. How do I do this efficiently? This operation is just a small part of the entire program, but will be called repeatedly. So I'm not sure if I should actually bother about the efficiency.
What I'm doing right now is that I first figure out where the spaces between words are and then add it to a List. I then iterate through the list and find 3 indices each representing the end word of each line. So the first index will be the space closest to 45, the next closest to 90, and the third closest to 135. I then use these indices to split the actual string, and add "\n" and "..." respectively. This is my code:
//maxCharsPerLine will be 45
public String splitString(String input, int maxCharsPerLine){
String output = "";
ArrayList<Integer> spaces = new ArrayList<Integer>();
// Logic to figure out after which word the sentence should be split so that we don't split in middle of a word
for(int index = 0; index < input.length(); index++){
if(input.charAt(index)==' '){
spaces.add(index);
}
}
//add index of last word of string
spaces.add(input.length());
int index1 = 0; int index2 = 0; int index3 = 0;
for(Integer index : spaces){
// find word closest to and less than maxCharsPerLine. This index will be used to find the last word in line1
if(index<=maxCharsPerLine)
index1 = index;
// find word closest to and less than 2*maxCharsPerLine. This index will be used to find the last word in line2
else if(index<=2*maxCharsPerLine)
index2 = index;
// find word closest to and less than 3*maxCharsPerLine, but exclude 3 chars for adding the dots (...). This index will be used to find the last word in line3
else if(index<=(3*maxCharsPerLine)-3)
index3 = index;
}
if(input.length()>maxCharsPerLine){
if(index1 > 0)
output = input.substring(0, index1);
if(index2 > 0)
output += "\n"+input.substring(index1+1, index2);
if(index3 > 0){
output += "\n"+input.substring(index2+1, index3);
if(input.length()>3*maxCharsPerLine)
output += "...";
}
}
//if length of input is < 45, just return the input
else
output = input;
return output;
}
Not sure in which scenarios this will fail. Is there a better way to do this?
Thanks.
You can use WordUtils.wrap method of Apache Commans Lang if 3 dots are not be considered for wrapping the line.
WordUtils.wrap(str, 45)
Code
public class test3 {
public static void main(String[] args) {
String S = "The condition is that the new line should not be added in the middle of a word. How do I do this efficiently? This operation is just a small part of the entire program, but will be called repeatedly. So I'm not sure if I should actually bother about the efficiency";
String Op = "";
String Op1 = "";
String Op2 = "";
String Op3 = "";
String Temp[] = S.split(" ");
int max_size_1 = 45;
int max_size_2 = 45;
int max_size_3 = 42;
int length = 0;
for (int i = 0; i < Temp.length; i++) {
length = length + Temp[i].length()+1;
if(length <= max_size_1) Op1 = Op1 + Temp[i]+" ";
else if(length <= Op1.length()+max_size_2) Op2 = Op2 +Temp[i]+" ";
else if(length <= Op1.length()+Op2.length()+max_size_3) Op3 = Op3 + Temp[i]+" ";
else {Op3 = Op3 +'\b' + "..."; i =Temp.length ; } //backspace
}
Op = Op1+"\n"+Op2+"\n"+Op3;
System.out.println(Op);
System.out.println(Op1.length()+" "+Op2.length()+" "+Op3.length()+" ");
}}
Output
The condition is that the new line should
not be added in the middle of a word. How do
I do this efficiently? This operation...
42 45 45
Here another solution, though it might be corrupted and needs to be edited.
int sizeOfString = input.lenght();
//the maximum lenght of a String
int aPartialStringLenght = 45;
String firstString;
String secondString;
String thirdString;
for(int x = 1; x <= 3; x++){
// looks for the last space before your 45th character
//sets the lenght for the third String to max. 42characters
if(x == 3){
aPartialStringLenght = 42;
}
while(!input.charAt(aPartialStringLenght*x).equals(" ")){
aPartialStringLenght -=1;
}
switch(x){
// gets the substring till your first partialString
case 1: firstString = input.substring(0, aPartialStringlenght);
aPartialStringLenght = 45;
// gets the substring from the end of your first partialString till the end of your second partialString
case 2: secondString = input.substring(firstString.lenght(), aPartialStringLenght + firstString.lenght());
aPartialStringLenght = 45;
// gets the substring from the end of your second partialString till till the end of your third partialString + "..."
case 3 thirdString = input.substring(firstString.lenght()+secondString.lenght(), aPartialStringLenght + firstString.lenght()+ secondString.lenght() )+"..."
aPartialStringLenght = 45;
}
}
Based on surya answer
public class test3 {
public static void main(String[] args) {
String S = "The condition is that the new line should not be added in the middle of a word. How do I do this efficiently? This operation is just a small part of the entire program, but will be called repeatedly. So I'm not sure if I should actually bother about the efficiency";
String F = WordUtils.wrap(S, 45);
String[] F1 = F.split(System.lineSeparator());
System.out.println(F1[0]);
System.out.println(F1[1]);
F1[2] = F1[2] +'\b'+'\b'+'\b'+"...";
System.out.println(F1[2]);
}
}
Output
The condition is that the new line should not
be added in the middle of a word. How do I do
this efficiently? This operation is jus...
My proposal is highly efficient, because:
It needs just two objects: the final string and a temporary StringBuilder, which is pre-sized,
And it does not waste time in pre-processing: Processes each character just once, and decides on the fly what to do.
And it is also flexible, because all the involved data are received as parameters:
public final class LinesSplitter
{
private LinesSplitter(){}
private static final char NL='\n';
public static String splitInLines(String text, int maxLineLength, int maxLines, String lastLineSuffix)
{
StringBuilder output=new StringBuilder((1 + maxLineLength) * maxLines);
int p=0;
int startOfLine=0;
int lastBlank=0;
int lastNonBlank=0;
int len=text.length();
String neededSuffix=text.length() > maxLineLength * maxLines
? lastLineSuffix
: "";
int lines=0;
while (lines < maxLines && p < len)
{
char c=text.charAt(p);
if (Character.isWhitespace(c))
{
lastBlank=p;
lastNonBlank=1 + p;
}
else if (p < len)
{
int maxLengthForCurrentLine=getMaxLength(maxLineLength, maxLines, 1 + lines, neededSuffix);
if (p - startOfLine == maxLengthForCurrentLine)
{
output.append(text, startOfLine, lastBlank);
String suffix=getSuffix(maxLineLength, maxLines, 1 + lines, neededSuffix);
if (!suffix.isEmpty())
{
output.append(suffix);
}
else
{
output.append(NL);
}
lines++;
startOfLine=lastNonBlank;
}
}
p++;
}
if (lines < maxLines && p - startOfLine > 0)
{
output.append(text, startOfLine, len);
}
return output.toString();
}
private final static int getMaxLength(int maxLineLength, int maxLines, int currentLine, String lastLineSuffix)
{
return currentLine == maxLines
? maxLineLength - lastLineSuffix.length()
: maxLineLength;
}
private final static String getSuffix(int maxLineLength, int maxLines, int currentLine, String lastLineSuffix)
{
return currentLine == maxLines
? lastLineSuffix
: "";
}
}
The only possible drawback is that it does not support several adjacent blanks.
I have started to write a code that would reverse every second set of 4 characters. eg. 1234567890987654. The result would be displayed as ("1234" "8765" "9098" "4567"). This would then be multiplied as in "1234" * "8765" * "9098" * "4567".
this code doesn't work and I would like some help.
My code currently is
public static void main(String[] args) {
String input = "1234567890987654";
System.out.println(result);
public static int reverse(String a) {
String newa = "";
String str = a;
char ch;
String[] array = str.split("(?<=\\G.{2})");
a = "array[]";
for (int i = 0 ; i < a.length() ; i=i+2) {
ch = a.charAt(i);
newa = ch + newa;
//System.out.println(newcardNum);
}
return newa;
}
Thanks in adavance
Let's start by creating a proper test framework (at least a toy testing framework) -
public static void main(String[] args) {
String input = "1234567890987654";
String expected = "1234" + "8765" + "9098" + "4567";
String result = reverse(input);
if (result.equals(expected)) {
System.out.println("result matches expected result");
} else {
System.out.println("result does not match expected result");
}
System.out.printf("input='%s', result = '%s'%n", input, result);
}
Now we can tell when the result we receive matches our expected result, and what the input and output String(s) are.
Next, we need to fix your reversing algorithm. You want to get 4 character then reverse 4 characters, so each iteration is 8 characters. Something like,
public static String reverse(String a) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < a.length(); i += 8) { // <-- increment by 8.
sb.append(a.substring(i, i + 4)); // <-- pass 1,4
// get characters 4 to 8
StringBuilder sb2 = new StringBuilder(a.substring(i + 4, i + 8));
// reverse and append
sb.append(sb2.reverse().toString());
}
return sb.toString();
}
Output is
result matches expected result
input='1234567890987654', result = '1234876590984567'
Edit Based on your comments below (and edited question), add something like this to main
String[] arr = new String[4];
long calc = 1; // <-- int would overflow
for (int count = 0, i = 0; i < result.length(); count++, i += 4) {
arr[count] = result.substring(i, i + 4);
calc *= Integer.parseInt(arr[count]);
}
System.out.printf("Array = %s, multiplication = %d%n", Arrays.toString(arr), calc);
And now the output is
result matches expected result
input='1234567890987654', result = '1234876590984567'
Array = [1234, 8765, 9098, 4567], multiplication = 449411337361660
The question is to generate the lexicographically greatest string given some string s.
So the aim is to find lexicographically greatest, unique(no repetitions) substring s1 from s.
We say that some subsequence s1 is greater than another subsequence s2 if s1 has more characters than s2 or s1 is lexicographically greater than s2 if equal length.
I/O are as follows:
Input is: babab
output is: ba
Second input is: nlhthgrfdnnlprjtecpdrthigjoqdejsfkasoctjijaoebqlrgaiakfsbljmpibkidjsrtkgrdnqsknbarpabgokbsrfhmeklrle
Second output is:
tsocrpkijgdqnbafhmle
This is what I wrote for my java code but my code fails on the second test case. Also I'm having a hard time understanding why second output isn't tsrqponmlkjihgfedcba.
Can somebody provide suggestions for a fix or even java code?
I think the algorithm has to be more efficient than generating all possible unique strings, sort them and find lexicographically largest one.
To make the question much clearer, if the input is babab, then all the possible unique combinations would be b, a, ba, ab. And the output will be ba because it's the longest and lexicographically greater than ab.
Note: this is not a homework assignment.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class mostBeautiful {
final static int MAX = 1000000;
static String[] permute;
static void permutation(String prefix, String str, int counter) {
int n = str.length();
//System.out.println("n is: "+ n);
if (n == 0) {
permute[counter] = prefix;
} else {
for (int i = 0; i < n; i++) {
//System.out.println("str is: "+ str);
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n), counter++);
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String s = bf.readLine();
char[] unique = new char[26];
int counter = 0;
String answer = "";
//System.out.println("s is: " + s);
int ascii = 0;
final int asciiAVal = 97;
final int asciiZVal = 122;
for (int i = 0; i < s.length(); i++) {
ascii = (int)s.charAt(i);
if (ascii < asciiAVal || ascii > asciiZVal) {
continue;
}
char ch = s.charAt(i);
unique[ch - 'a'] = ch;
}
String result = "";
for (int j = 25; j >= 0; j--) {
result += unique[j];
}
result = result.trim();
System.out.println(result);
int size = result.length() * (result.length() - 1);
permute = new String[size];
permutation("", result, counter);
for (int i = 1; i < size; i++) {
if (permute[i].compareTo(permute[i - 1]) > 0){
answer = permute[i];
} else {
answer = permute[i - 1];
}
}
System.out.println("answer is: " + answer);
}
}
After thinking about this problem in many ways, I have determined a divide-and-conquer algorithm that gets the results right:
Algorithm - Pseudocode
Assuming some input string, S defined as a concatenation of two substrings A + B, we compute the lexicographically greatest string recursively as:
LexMax(S) = Merge(LexMax(A),LexMax(B))
Where
LexMax(S)
{
if Length(S) = 1
return S
else
{
LMA = LexMax(S[0:Length/2])
LMB = LexMax(S[Length/2:end])
return Merge(LMA,LMB)
}
}
Merge(A,B)
{
Sa = A
Sb = B
for n = 0:Length(A)
{
if Sb contains A[n]
{
if A[n+1:end] contains character > A[n]
Remove A[n] from Sa
else
Remove A[n] from Sb
}
}
return Sa + Sb
}
Java Code
Coming soon!
Example
Given an input string
cefcfdabbcfed
Divide it into
cefcfda
bbcfed
Assuming the function works we have:
LexMax("cefcfda") = "efcda"
LexMax("bbcfed") = "bcfed"
Merging works as follows:
e: efcda bcfed
In both substrings, greater value found to right of e in left substring, remove from left
f: fcda bcfed
In both substrings, no greater value in left substring, remove from right
c: fcda bced
In both substrings, greater value found to right of c in left substring, remove from left
d: fda bced
In both substrings, no greater value in left substring, remove from right
a: fda bce
Not in both substrings, do nothing
Final result:
LexMax(cefcfdabbcfed) = fdabce
This is not a direct answer, but doesn't this code meet the requirement as you explained it in the discussion above?
final String x = "saontehusanoethusnaoteusnaoetuh";
final SortedSet<Character> chars =
new TreeSet<Character>(Collections.reverseOrder());
for (char c : x.toCharArray()) chars.add(c);
System.out.println(chars);
Lexicographic order is an order in which words are displayed in alphabetical order using the appearance of letters in the word.It is also know as dictionary order or alphabetical order.For ex:-"Africa" is smaller than "Bangladesh" ,"He" is smaller than "he".
public class LexicographicExample {
public static void main(String a[]) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the String:-");
String str = sc.nextLine();
System.out.println("Enter the length");
int count = sc.nextInt();
List<String> list = new ArrayList<String>();
for (int i = 0; i < str.length(); i = i + 1) {
if (str.length() - i >= count) {
list.add(str.substring(i, count + i));
}
}
Collections.sort(list);
System.out.println("Smallest subString:-" + list.get(0));
System.out.println("Largest subString:-" + list.get(list.size() - 1));
}
}
For reference ,refer this link http://techno-terminal.blogspot.in/2015/09/java-program-to-find-lexicographically.html
"tsrqponmlkjihgfedcba" is not the answer because it is not a subsequence of the input. The definition of subsequence requires that the characters of the subsequence occur in the original sequence in the same order. For example, "abc" is a subsequence of "apbqcr", while "cba" is not.
As to the solution, I think a simple greedy algorithm would suffice. First, one has to understand that the maximum possible length of the output is the number of unique symbols (say, N) in the input. Since any output shorter than that would not be the greatest one, it has to be exactly N symbols long. The rest of the procedure is simple and at most quadratic in time complexity: one has to go through the input string and at each step pick the lexicographically highest symbol such that the part of the string to the left of it would still contain all the "unused" symbols.
As an example, consider a string "bacb". The first symbol can be 'a' or 'b', since in both cases the remainder contains both of the other letters. 'b' is greater, so we pick it. Now for "acb" we can only pick 'a' and than 'c' according to that condition, so we end up with "bac" for output.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
class aaa {
public static void main(String args[]) throws Exception {
Scanner scan = new Scanner(System.in);
// int n = scan.nextInt();
String s = scan.next();
HashMap<Character, Node5> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
if (!map.containsKey(s.charAt(i))) {
Node5 node = new Node5();
node.nl.add(i);
node.li = i;
map.put(s.charAt(i), node);
} else {
Node5 rn = map.get(s.charAt(i));
rn.nl.add(i);
rn.li = i;
map.put(s.charAt(i), rn);
}
}
String s1 = "";
int index = -1;
for (int i = 25; i >= 0; i--) {
if (map.containsKey((char) (97 + i))) {
if (map.get((char) (97 + i)).li > index) {
for (int j = 0; j < map.get((char) (97 + i)).nl.size(); j++) {
if (map.get((char) (97 + i)).nl.get(j) > index) {
s1 += (char) (97 + i);
index = map.get((char) (97 + i)).nl.get(j);
}
}
}
}
}
System.out.println(s1);
scan.close();
}
}
class Node5 {
int li;
ArrayList<Integer> nl;
public Node5() {
this.nl = new ArrayList<>();
}
}
If I have a decimal number, how do I convert it to base 36 in Java?
Given a number i, use Integer.toString(i, 36).
See the documentation for Integer.toString
http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#toString(int,%20int)
toString
public static String toString(int i, int radix)
....
The following ASCII characters are used as digits:
0123456789abcdefghijklmnopqrstuvwxyz
What is radix? You're in luck for Base 36 (and it makes sense)
http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#MAX_RADIX
public static final int MAX_RADIX 36
The following can work for any base, not just 36. Simply replace the String contents of code.
Encode:
int num = 586403532;
String code = "0123456789abcdefghijklmnopqrstuvwxyz";
String text = "";
int j = (int)Math.ceil(Math.log(num)/Math.log(code.length()));
for(int i = 0; i < j; i++){
//i goes to log base code.length() of num (using change of base formula)
text += code.charAt(num%code.length());
num /= code.length();
}
Decode:
String text = "0vn4p9";
String code = "0123456789abcdefghijklmnopqrstuvwxyz";
int num = 0;
int j = text.length();
for(int i = 0; i < j; i++){
num += code.indexOf(text.charAt(0))*Math.pow(code.length(), i);
text = text.substring(1);
}
First you have to convert your number it into the internal number format of Java (which happens to be 2-based, but this does not really matter here), for example by Integer.parseInt() (if your number is an integer less than 2^31). Then you can convert it from int to the desired output format. The method Integer.toString(i, 36) does this by using 0123456789abcdefghijklmnopqrstuvwxyz as digits (the decimal digits 0-9 and lower case english letters in alphabetic order). If you want some other digits, you can either convert the result by replacing the "digits" (for example toUpperCase), or do the conversion yourself - it is no magic, simply a loop of taking the remainder modulo 36 and dividing by 36 (with a lookup of the right digit).
If your number is longer than what int offers you may want to use long (with Long) or BigInteger instead, they have similar radix-converters.
If your number has "digits after the point", it is a bit more difficult, as most (finite) base-X-numbers are not exactly representable as (finite) base-Y-numbers if (a power of) Y is not a multiple of X.
This code works:
public class Convert {
public static void main(String[] args) {
int num= 2147483647;
String text="ABCD1";
System.out.println("num: " + num + "=>" + base10ToBase36(num));
System.out.println("text: " +text + "=>" + base36ToBase10(text));
}
private static String codeBase36 = "0123456789abcdefghijklmnopqrstuvwxyz";
//"0123456789 abcdefghij klmnopqrst uvwxyz"
//"0123456789 0123456789 0123456789 012345"
private static String max36=base10ToBase36(Integer.MAX_VALUE);
public static String base10ToBase36(int inNum) {
if(inNum<0) {
throw new NumberFormatException("Value "+inNum +" to small");
}
int num = inNum;
String text = "";
int j = (int)Math.ceil(Math.log(num)/Math.log(codeBase36.length()));
for(int i = 0; i < j; i++){
text = codeBase36.charAt(num%codeBase36.length())+text;
num /= codeBase36.length();
}
return text;
}
public static int base36ToBase10(String in) {
String text = in.toLowerCase();
if(text.compareToIgnoreCase(max36)>0) {
throw new NumberFormatException("Value "+text+" to big");
}
if(!text.replaceAll("(\\W)","").equalsIgnoreCase(text)){
throw new NumberFormatException("Value "+text+" false format");
}
int num=0;
int j = text.length();
for(int i = 0; i < j; i++){
num += codeBase36.indexOf(text.charAt(text.length()-1))*Math.pow(codeBase36.length(), i);
text = text.substring(0,text.length()-1);
}
return num;
}
}
If you dont want to use Integer.toString(Num , base) , for instance, in my case which I needed a 64 bit long variable, you can use the following code:
Using Lists in JAVA facilitates this conversion
long toBeConverted=10000; // example, Initialized by 10000
List<Character> charArray = new ArrayList<Character>();
List<Character> charArrayFinal = new ArrayList<Character>();
int length=10; //Length of the output string
long base = 36;
while(toBeConverted!=0)
{
long rem = toBeConverted%base;
long quotient = toBeConverted/base;
if(rem<10)
rem+=48;
else
rem+=55;
charArray.add((char)rem);
toBeConverted=quotient;
}
// make the array in the reverse order
for(int i=length-1;i>=0;--i){
if(i>=charArray.size()){
charArrayFinal.add((char) 48); // sends 0 to fix the length of the output List
} else {
charArrayFinal.add(charArray.get(i));
}
}
Example:
(278197)36=5YNP
Maybe I'm late to the party, but this is the solution I was using for getting Calc/Excel cell names by their index:
public static void main(final String[] args) {
final String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
System.out.println(toCustomBase(0, base));
System.out.println(toCustomBase(2, base));
System.out.println(toCustomBase(25, base));
System.out.println(toCustomBase(26, base));
System.out.println(toCustomBase(51, base));
System.out.println(toCustomBase(52, base));
System.out.println(toCustomBase(520, base));
}
public static String toCustomBase(final int num, final String base) {
final int baseSize = base.length();
if(num < baseSize) {
return String.valueOf(base.charAt(num));
}
else {
return toCustomBase(num / baseSize - 1, base) + base.charAt(num % baseSize);
}
}
Results:
A
C
Z
AA
AZ
BA
TA
Basically the solution accepts any custom radix. The idea was commandeered from here.
Not sure if the above answers did help but noting 'decimal' and 'to base36' I assume you want to convert a numeric value to base36. And as long as the Long value of the raw figure is within (0 - Long.MAX_VALUE):
String someNumericString = "9223372036854";
Long l = Long.valueOf(someNumericString);
String bases36 = Long.toString(l, 36);
System.out.println("base36 value: "+bases36);
output: 39p5pkj5i
Here is a method to convert base 10 to any given base.
public char[] base10Converter(int number, int finalBase) {
int quo;
int rem;
char[] res = new char[1];
do {
rem = number % finalBase;
quo = number / finalBase;
res = Arrays.copyOf(res, res.length + 1);
if (rem < 10) {
//Converting ints using ASCII values
rem += 48;
res[res.length - 1] = (char) rem;
} else {
//Convert int > 9 to A, B, C..
rem += 55;
res[res.length - 1] = (char) rem;
}
number /= finalBase;
} while (quo != 0);
//Reverse array
char[] temp = new char[res.length];
for (int i = res.length - 1, j = 0; i > 0; i--) {
temp[j++] = res[i];
}
return temp;
}
I got this code from this website in JavaScript, and this is my version in java:
public static String customBase (int N, String base) {
int radix = base.length();
String returns = "";
int Q = (int) Math.floor(Math.abs(N));
int R = 0;
while (Q != 0) {
R = Q % radix;
returns = base.charAt(R) + returns;
Q /= radix;
}
if(N == 0) {
return String.valueOf(base.toCharArray()[0]);
}
return N < 0 ? "-" + returns : returns;
}
This supports negative numbers and custom bases.
Decimal Addon:
public static String customBase (double N, String base) {
String num = (String.valueOf(N));
String[] split = num.split("\\.");
if(split[0] == "" || split[1] == "") {
return "";
}
return customBase(Integer.parseInt(split[0]), base)+ "." + customBase(Integer.parseInt(split[1]), base);
}
This can be helpful to you.The operation being performed on the 4 digit alphanumeric String and decimal number below 1679615. You can Modify code accordingly.
char[] alpaNum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
String currentSeries = "";
int num = 481261;
String result = "";
String baseConversionStr = "";
boolean flag = true;
do
{
baseConversionStr = Integer.toString(num % 36) + baseConversionStr;
String position = "";
if(flag)
{
flag = false;
position = baseConversionStr;
}
else
{
position = Integer.toString(num % 36);
}
result += alpaNum[new Integer(position)];
num = num/36;
}
while (num > 0);
StringBuffer number = new StringBuffer(result).reverse();
String finalString = "";
if(number.length()==1)
{
finalString = "000"+articleNo;
}
else if(number.length()==2)
{
finalString = "00"+articleNo;
}
else if(number.length()==3)
{
finalString = "0"+articleNo;
}
currentSeries = finalString;