Converting Roman Numerals To Decimal - java

I have managed to get my code to convert most Roman numerals to its appropriate decimal value. But it doesn't work for some exceptional cases. Example : XCIX = 99 but my code prints 109.
Here is my code.
public static int romanConvert(String roman)
{
int decimal = 0;
String romanNumeral = roman.toUpperCase();
for(int x = 0;x<romanNumeral.length();x++)
{
char convertToDecimal = roman.charAt(x);
switch (convertToDecimal)
{
case 'M':
decimal += 1000;
break;
case 'D':
decimal += 500;
break;
case 'C':
decimal += 100;
break;
case 'L':
decimal += 50;
break;
case 'X':
decimal += 10;
break;
case 'V':
decimal += 5;
break;
case 'I':
decimal += 1;
break;
}
}
if (romanNumeral.contains("IV"))
{
decimal-=2;
}
if (romanNumeral.contains("IX"))
{
decimal-=2;
}
if (romanNumeral.contains("XL"))
{
decimal-=10;
}
if (romanNumeral.contains("XC"))
{
decimal-=10;
}
if (romanNumeral.contains("CD"))
{
decimal-=100;
}
if (romanNumeral.contains("CM"))
{
decimal-=100;
}
return decimal;
}

It will be good if you traverse in reverse.
public class RomanToDecimal {
public static void romanToDecimal(java.lang.String romanNumber) {
int decimal = 0;
int lastNumber = 0;
String romanNumeral = romanNumber.toUpperCase();
/* operation to be performed on upper cases even if user
enters roman values in lower case chars */
for (int x = romanNumeral.length() - 1; x >= 0 ; x--) {
char convertToDecimal = romanNumeral.charAt(x);
switch (convertToDecimal) {
case 'M':
decimal = processDecimal(1000, lastNumber, decimal);
lastNumber = 1000;
break;
case 'D':
decimal = processDecimal(500, lastNumber, decimal);
lastNumber = 500;
break;
case 'C':
decimal = processDecimal(100, lastNumber, decimal);
lastNumber = 100;
break;
case 'L':
decimal = processDecimal(50, lastNumber, decimal);
lastNumber = 50;
break;
case 'X':
decimal = processDecimal(10, lastNumber, decimal);
lastNumber = 10;
break;
case 'V':
decimal = processDecimal(5, lastNumber, decimal);
lastNumber = 5;
break;
case 'I':
decimal = processDecimal(1, lastNumber, decimal);
lastNumber = 1;
break;
}
}
System.out.println(decimal);
}
public static int processDecimal(int decimal, int lastNumber, int lastDecimal) {
if (lastNumber > decimal) {
return lastDecimal - decimal;
} else {
return lastDecimal + decimal;
}
}
public static void main(java.lang.String args[]) {
romanToDecimal("XIV");
}
}

Try this - It is simple and compact and works quite smoothly:
public static int ToArabic(string number) {
if (number == string.Empty) return 0;
if (number.StartsWith("M")) return 1000 + ToArabic(number.Remove(0, 1));
if (number.StartsWith("CM")) return 900 + ToArabic(number.Remove(0, 2));
if (number.StartsWith("D")) return 500 + ToArabic(number.Remove(0, 1));
if (number.StartsWith("CD")) return 400 + ToArabic(number.Remove(0, 2));
if (number.StartsWith("C")) return 100 + ToArabic(number.Remove(0, 1));
if (number.StartsWith("XC")) return 90 + ToArabic(number.Remove(0, 2));
if (number.StartsWith("L")) return 50 + ToArabic(number.Remove(0, 1));
if (number.StartsWith("XL")) return 40 + ToArabic(number.Remove(0, 2));
if (number.StartsWith("X")) return 10 + ToArabic(number.Remove(0, 1));
if (number.StartsWith("IX")) return 9 + ToArabic(number.Remove(0, 2));
if (number.StartsWith("V")) return 5 + ToArabic(number.Remove(0, 1));
if (number.StartsWith("IV")) return 4 + ToArabic(number.Remove(0, 2));
if (number.StartsWith("I")) return 1 + ToArabic(number.Remove(0, 1));
throw new ArgumentOutOfRangeException("something bad happened");
}

assuming the hash looks something like this
Hashtable<Character, Integer> ht = new Hashtable<Character, Integer>();
ht.put('i',1);
ht.put('x',10);
ht.put('c',100);
ht.put('m',1000);
ht.put('v',5);
ht.put('l',50);
ht.put('d',500);
then the logic gets pretty simple going by digit right to left
public static int rtoi(String num)
{
int intNum=0;
int prev = 0;
for(int i = num.length()-1; i>=0 ; i--)
{
int temp = ht.get(num.charAt(i));
if(temp < prev)
intNum-=temp;
else
intNum+=temp;
prev = temp;
}
return intNum;
}

Following your logic of reducing 2 on IX you should reduce 20 on XC 200 on CM and so on.

Less code, more efficient. Not so clearer, sorry!
public int evaluateRomanNumerals(String roman) {
return (int) evaluateNextRomanNumeral(roman, roman.length() - 1, 0);
}
private double evaluateNextRomanNumeral(String roman, int pos, double rightNumeral) {
if (pos < 0) return 0;
char ch = roman.charAt(pos);
double value = Math.floor(Math.pow(10, "IXCM".indexOf(ch))) + 5 * Math.floor(Math.pow(10, "VLD".indexOf(ch)));
return value * Math.signum(value + 0.5 - rightNumeral) + evaluateNextRomanNumeral(roman, pos - 1, value);
}

Imperative + recursive solutions with validation step and online testing
To avoid useless calculations and to make sure the roman numerals format is correct, we need to check the input with a regular expression.
String regex = "^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$";
Explanation of the regular expression in details
Explanation of the regular expression symbols used
Differences between regex functions matches() and find()
Why is MMMCMXCIX (= 3999) the maximum value with standard roman numerals notation
Imperative solution
public static int romanToDecimal(String s) {
if (s == null || s.isEmpty() || !s.matches("^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"))
return -1;
final Matcher matcher = Pattern.compile("M|CM|D|CD|C|XC|L|XL|X|IX|V|IV|I").matcher(s);
final int[] decimalValues = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
final String[] romanNumerals = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
int result = 0;
while (matcher.find())
for (int i = 0; i < romanNumerals.length; i++)
if (romanNumerals[i].equals(matcher.group(0)))
result += decimalValues[i];
return result;
}
try online | try optimized version with comments/explanation online
UPDATE: here are two clever recursive proposals from this thread I solved adding validation step
Recursive solution 1 (original answer)
public class RomanToDecimalConverter {
private static double evaluateNextRomanNumeral(String roman, int pos, double rightNumeral) {
if (pos < 0) return 0;
char ch = roman.charAt(pos);
double value = Math.floor(Math.pow(10, "IXCM".indexOf(ch))) + 5 * Math.floor(Math.pow(10, "VLD".indexOf(ch)));
return value * Math.signum(value + 0.5 - rightNumeral) + evaluateNextRomanNumeral(roman, pos - 1, value);
}
public static int evaluateRomanNumerals(String s) {
if (s == null || s.isEmpty() || !s.matches("^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"))
return -1;
return (int) evaluateNextRomanNumeral(s, s.length() - 1, 0);
}
}
try online
Recursive solution 2 (original answer)
public class RomanToDecimalConverter {
private static int convertRec(String s) {
if (s.isEmpty()) return 0;
if (s.startsWith("M")) return 1000 + convertRec(s.substring(1));
else if (s.startsWith("CM")) return 900 + convertRec(s.substring(2));
else if (s.startsWith("D")) return 500 + convertRec(s.substring(1));
else if (s.startsWith("CD")) return 400 + convertRec(s.substring(2));
else if (s.startsWith("C")) return 100 + convertRec(s.substring(1));
else if (s.startsWith("XC")) return 90 + convertRec(s.substring(2));
else if (s.startsWith("L")) return 50 + convertRec(s.substring(1));
else if (s.startsWith("XL")) return 40 + convertRec(s.substring(2));
else if (s.startsWith("X")) return 10 + convertRec(s.substring(1));
else if (s.startsWith("IX")) return 9 + convertRec(s.substring(2));
else if (s.startsWith("V")) return 5 + convertRec(s.substring(1));
else if (s.startsWith("IV")) return 4 + convertRec(s.substring(2));
else if (s.startsWith("I")) return 1 + convertRec(s.substring(1));
throw new IllegalArgumentException("Unexpected roman numerals");
}
public static int convert(String s) {
if (s == null || s.isEmpty() || !s.matches("^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"))
return -1;
return convertRec(s);
}
}
try online

// Author: Francisco Edmundo
private int translateNumber(String texto) {
int n = 0;
int numeralDaDireita = 0;
for (int i = texto.length() - 1; i >= 0; i--) {
int valor = (int) translateNumber(texto.charAt(i));
n += valor * Math.signum(valor + 0.5 - numeralDaDireita);
numeralDaDireita = valor;
}
return n;
}
private double translateNumber(char caractere) {
return Math.floor(Math.pow(10, "IXCM".indexOf(caractere))) + 5 * Math.floor(Math.pow(10, "VLD".indexOf(caractere)));
}

You can check following code. This code should work on all cases. Also it checks null or empty input and faulty input (Let's say you tried with ABXI)
import java.util.HashMap;
import org.apache.commons.lang3.StringUtils;
public class RomanToDecimal {
private HashMap<Character, Integer> map;
public RomanToDecimal() {
map = new HashMap<>();
map.put('I', 1);
map.put('V', 5);
map.put('X', 10);
map.put('L', 50);
map.put('C', 100);
map.put('D', 500);
map.put('M', 1000);
}
private int getRomanNumeralValue(char ch) {
if (map.containsKey(ch)) {
return map.get(ch);
}
else {
throw new RuntimeException("Roman numeral string contains invalid characters " + ch);
}
}
public int convertRomanToDecimal(final String pRomanNumeral) {
if (StringUtils.isBlank(pRomanNumeral)) {
throw new RuntimeException("Roman numeral string is either null or empty");
}
else {
int index = pRomanNumeral.length() - 1;
int result = getRomanNumeralValue(pRomanNumeral.charAt(index));
for (int i = index - 1; i >= 0; i--) {
if (getRomanNumeralValue(pRomanNumeral.charAt(i)) >= getRomanNumeralValue(pRomanNumeral.charAt(i + 1))) {
result = result + getRomanNumeralValue(pRomanNumeral.charAt(i));
}
else {
result = result - getRomanNumeralValue(pRomanNumeral.charAt(i));
}
}
return result;
}
}
public static void main(String... args){
System.out.println(new RomanToDecimal().convertRomanToDecimal("XCIX"));
}
}

Full version with error checking and test all valid values in both directions (and some invalid cases).
RomanNumeral.java
import java.util.ArrayList;
import java.util.TreeMap;
/**
* Convert to and from a roman numeral string
*/
public class RomanNumeral {
// used for converting from arabic number
final static TreeMap<Integer, String> mapArabic = new TreeMap<Integer, String>();
// used for converting from roman numeral
final static ArrayList<RomanDigit> mapRoman = new ArrayList<RomanDigit>();
final static int MAX_ARABIC = 3999;
static {
mapArabic.put(1000, "M");
mapArabic.put(900, "CM");
mapArabic.put(500, "D");
mapArabic.put(400, "CD");
mapArabic.put(100, "C");
mapArabic.put(90, "XC");
mapArabic.put(50, "L");
mapArabic.put(40, "XL");
mapArabic.put(10, "X");
mapArabic.put(9, "IX");
mapArabic.put(5, "V");
mapArabic.put(4, "IV");
mapArabic.put(1, "I");
mapRoman.add(new RomanDigit("M", 1000, 3, 1000));
mapRoman.add(new RomanDigit("CM", 900, 1, 90));
mapRoman.add(new RomanDigit("D", 500, 1, 100));
mapRoman.add(new RomanDigit("CD", 400, 1, 90));
mapRoman.add(new RomanDigit("C", 100, 3, 100));
mapRoman.add(new RomanDigit("XC", 90, 1, 9));
mapRoman.add(new RomanDigit("L", 50, 1, 10));
mapRoman.add(new RomanDigit("XL", 40, 1, 9));
mapRoman.add(new RomanDigit("X", 10, 3, 10));
mapRoman.add(new RomanDigit("IX", 9, 1, 0));
mapRoman.add(new RomanDigit("V", 5, 1, 1));
mapRoman.add(new RomanDigit("IV", 4, 1, 0));
mapRoman.add(new RomanDigit("I", 1, 3, 1));
}
static final class RomanDigit {
public final String numeral;
public final int value;
public final int maxConsecutive;
public final int maxNextValue;
public RomanDigit(String numeral, int value, int maxConsecutive, int maxNextValue) {
this.numeral = numeral;
this.value = value;
this.maxConsecutive = maxConsecutive;
this.maxNextValue = maxNextValue;
}
}
/**
* Convert an arabic integer value into a roman numeral string
*
* #param n The arabic integer value
* #return The roman numeral string
*/
public final static String toRoman(int n) {
if (n < 1 || n > MAX_ARABIC) {
throw new NumberFormatException(String.format("Invalid arabic value: %d, must be > 0 and < %d", n, MAX_ARABIC));
}
int leDigit = mapArabic.floorKey(n);
//System.out.println("\t*** floor of " + n + " is " + leDigit);
if (n == leDigit) {
return mapArabic.get(leDigit);
}
return mapArabic.get(leDigit) + toRoman(n - leDigit);
}
/**
* Convert a roman numeral string into an arabic integer value
* #param s The roman numeral string
* #return The arabic integer value
*/
public final static int toInt(String s) throws NumberFormatException {
if (s == null || s.length() == 0) {
throw new NumberFormatException("Invalid roman numeral: a non-empty and non-null value must be given");
}
int i = 0;
int iconsecutive = 0; // number of consecutive same digits
int pos = 0;
int sum = 0;
RomanDigit prevDigit = null;
while (pos < s.length()) {
RomanDigit d = mapRoman.get(i);
if (!s.startsWith(mapRoman.get(i).numeral, pos)) {
i++;
// this is the only place we advance which digit we are checking,
// so if it exhausts the digits, then there is clearly a digit sequencing error or invalid digit
if (i == mapRoman.size()) {
throw new NumberFormatException(
String.format("Invalid roman numeral at pos %d: invalid sequence '%s' following digit '%s'",
pos, s.substring(pos), prevDigit != null ? prevDigit.numeral : ""));
}
iconsecutive = 0;
continue;
}
// we now have the match for the next roman numeral digit to check
iconsecutive++;
if (iconsecutive > d.maxConsecutive) {
throw new NumberFormatException(
String.format("Invalid roman numeral at pos %d: more than %d consecutive occurences of digit '%s'",
pos, d.maxConsecutive, d.numeral));
}
// invalid to encounter a higher digit sequence than the previous digit expects to have follow it
// (any digit is valid to start a roman numeral - i.e. when prevDigit == null)
if (prevDigit != null && prevDigit.maxNextValue < d.value) {
throw new NumberFormatException(
String.format("Invalid roman numeral at pos %d: '%s' cannot follow '%s'",
pos, d.numeral, prevDigit.numeral));
}
// good to sum
sum += d.value;
if (sum > MAX_ARABIC) {
throw new NumberFormatException(
String.format("Invalid roman numeral at pos %d: adding '%s' exceeds the max value of %d",
pos, d.numeral, MAX_ARABIC));
}
pos += d.numeral.length();
prevDigit = d;
}
return sum;
}
}
Main.java
public class Main {
public static void main(String[] args) {
System.out.println("TEST arabic integer => roman numeral string");
for (int i = 0; i<= 4000; i++) {
String s;
try {
s = RomanNumeral.toRoman(i);
}
catch(NumberFormatException ex) {
s = ex.getMessage();
}
System.out.println(i + "\t =\t " + s);
}
System.out.println("TEST roman numeral string => arabic integer");
for (int i = 0; i<= 4000; i++) {
String s;
String msg;
try {
s = RomanNumeral.toRoman(i);
int n = testToInt(s);
assert(i == n); // ensure it is reflexively converting
}
catch (NumberFormatException ex) {
System.out.println(ex.getMessage() + "\t =\t toInt() skipped");
}
}
testToInt("MMMM");
testToInt("XCX");
testToInt("CDC");
testToInt("IVI");
testToInt("XXC");
testToInt("CCD");
testToInt("MDD");
testToInt("DD");
testToInt("CLL");
testToInt("LL");
testToInt("IIX");
testToInt("IVX");
testToInt("IIXX");
testToInt("XCIX");
testToInt("XIWE");
// Check validity via a regexp for laughs
String s = "IX";
System.out.println(s + " validity is " + s.matches("M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})"));
}
private final static int testToInt(String s) {
String msg;
int n=0;
try {
n = RomanNumeral.toInt(s);
msg = Integer.toString(n);
}
catch(NullPointerException | NumberFormatException ex) {
msg = ex.getMessage();
}
System.out.println(s + "\t =\t " + msg);
return n;
}
}
Output
TEST arabic integer => roman numeral string
0 = Invalid arabic value: 0, must be > 0 and < 3999
1 = I
2 = II
3 = III
4 = IV
5 = V
6 = VI
7 = VII
8 = VIII
9 = IX
10 = X
... [snip] ...
3988 = MMMCMLXXXVIII
3989 = MMMCMLXXXIX
3990 = MMMCMXC
3991 = MMMCMXCI
3992 = MMMCMXCII
3993 = MMMCMXCIII
3994 = MMMCMXCIV
3995 = MMMCMXCV
3996 = MMMCMXCVI
3997 = MMMCMXCVII
3998 = MMMCMXCVIII
3999 = MMMCMXCIX
4000 = Invalid arabic value: 4000, must be > 0 and < 3999
TEST roman numeral string => arabic integer
Invalid arabic value: 0, must be > 0 and < 3999 = toInt() skipped
I = 1
II = 2
III = 3
IV = 4
V = 5
VI = 6
VII = 7
VIII = 8
IX = 9
X = 10
... [snip] ...
MMMCMLXXXVIII = 3988
MMMCMLXXXIX = 3989
MMMCMXC = 3990
MMMCMXCI = 3991
MMMCMXCII = 3992
MMMCMXCIII = 3993
MMMCMXCIV = 3994
MMMCMXCV = 3995
MMMCMXCVI = 3996
MMMCMXCVII = 3997
MMMCMXCVIII = 3998
MMMCMXCIX = 3999
Invalid arabic value: 4000, must be > 0 and < 3999 = toInt() skipped
MMMM = Invalid roman numeral at pos 3: more than 3 consecutive occurences of digit 'M'
XCX = Invalid roman numeral at pos 2: 'X' cannot follow 'XC'
CDC = Invalid roman numeral at pos 2: 'C' cannot follow 'CD'
IVI = Invalid roman numeral at pos 2: 'I' cannot follow 'IV'
XXC = Invalid roman numeral at pos 2: invalid sequence 'C' following digit 'X'
CCD = Invalid roman numeral at pos 2: invalid sequence 'D' following digit 'C'
MDD = Invalid roman numeral at pos 2: more than 1 consecutive occurences of digit 'D'
DD = Invalid roman numeral at pos 1: more than 1 consecutive occurences of digit 'D'
CLL = Invalid roman numeral at pos 2: more than 1 consecutive occurences of digit 'L'
LL = Invalid roman numeral at pos 1: more than 1 consecutive occurences of digit 'L'
IIX = Invalid roman numeral at pos 2: invalid sequence 'X' following digit 'I'
IVX = Invalid roman numeral at pos 2: invalid sequence 'X' following digit 'IV'
IIXX = Invalid roman numeral at pos 2: invalid sequence 'XX' following digit 'I'
XCIX = 99
XIWE = Invalid roman numeral at pos 2: invalid sequence 'WE' following digit 'I'
IX validity is true

Lets look at this problem with 3 different scenarios
Scenario 1:
When we see a pattern like the following
'IIIIII' or 'XXXXX' or 'CCCC'
where all characters as the same: We add the value of each characters in the pattern
'IIIIII' gives us '6'
'XXXXX' gives us '50'
'CCCC' gives us '400'
Scenario 2:
When we see any 2 consecutive characters different where first is smaller in value then the 2nd
'IX' or 'XC'
We subtract the value of first from second e.g.
second:'X' gives us '10'
first: 'I' gives us '1'
second - first : 10 - 1 = 9
Scenario 3:
When we see a any 2 consecutive characters different where first is greater in value then the second
'XI' or 'CX'
We add first and second e.g.
second:'I' gives us '10'
first: 'X' gives us '1'
first + second : 10 + 1 = 11
Now we can find the result if we do this recursively.
Here is the java implementation :
//An array to be used for faster comparisons and reading the values
private int[] letters26 = new int[26];
private void init () {
letters26['I' - 'A'] = 1;
letters26['V' - 'A'] = 5;
letters26['X' - 'A'] = 10;
letters26['L' - 'A'] = 50;
letters26['C' - 'A'] = 100;
letters26['D' - 'A'] = 500;
letters26['M' - 'A'] = 1000;
}
public int convertRomanToInteger(String s) {
//Initialize the array
init();
return _convertRomanToInteger(s.toCharArray(), 0);
}
//Recursively calls itself as long as 2 consecutive chars are different
private int _convertRomanToInteger(char[] s, int index) {
int ret = 0;
char pre = s[index];//Char from the given index
ret = _getValue(pre);
//Iterate through the rest of the string
for (int i = index + 1; i < s.length; i++) {
if (compare(s[i], s[i - 1]) == 0) {
//Scenario 1:
//If 2 consecutive chars are similar, just add them
ret += _getValue(s[i]);
} else if (compare(s[i], s[i - 1]) > 0) {
//Scenario 2:
//If current char is greater than the previous e.g IX ('I' s[i - 1] and 'X' s[i - 1])
//We need to calculate starting from 'i' and subtract the calculation ('ret')
//done so far in current call
return _convertRomanToInteger(s, i) - ret;
} else {
//Scenario 3:
//If current char is smaller than the previous e.g XI ('X' s[i - 1] and 'I' s[i - 1])
//We need to calculate starting from 'i' and subtract the result
//from the calculation done so far in current call
return ret + _convertRomanToInteger(s, i);
}
}
return ret;
}
//Helper function for comparison
private int compare(char a, char b) {
return letters26[Character.toUpperCase(a) - 'A']
- letters26[Character.toUpperCase(b) - 'A'];
}
private int _getValue(char c) {
return letters26[Character.toUpperCase(c) - 'A'];
}

Despite the fact that a lot of solutions have been already proposed.
I guess that the following one will be short and clear:
public class RomanToInteger {
public static int romanToInt(String roman) {
final Map<Character, Integer> map = Map.of('I', 1,
'V', 5,
'X', 10,
'L', 50,
'C', 100,
'D', 500,
'M', 1000);
int result = 0;
for (int index = 0; index < roman.length(); index++) {
final int curNumber = map.get(roman.charAt(index));
if (index > 0 && curNumber > map.get(roman.charAt(index - 1))) {
// add current number & remove previous one twice:
// first: we add it before (when it was current number) and removing it for this current number
// second: for correct conversion to roman numbers
result += curNumber - 2 * map.get(roman.charAt(index - 1));
} else {
result += curNumber;
}
}
System.out.printf("%8s -> %4d\n", roman, result);
return result;
}
public static void main(String[] args) {
String[] romans = {"I", "II", "III", "V", "X", "XIV", "XVII", "XX", "XXV",
"XXX", "XXXVIII", "XLIX", "LXIII", "LXXXI", "XCVII", "XCVIII", "XCIX",
"C", "CI", "CCXLVIII", "CCLIII", "DCCXCIX", "MCCCXXV", "MCM", "MM",
"MMCDLVI", "MDCCXV"};
final Instant startTimeIter = Instant.now();
for (String roman : romans) {
romanToInt(roman);
}
final Instant endTimeIter = Instant.now();
System.out.printf("Elapsed time: %d ms\n", Duration.between(startTimeIter, endTimeIter).toMillis());
}
}
Output:
I -> 1
II -> 2
III -> 3
...
MMCDLVI -> 2456
MDCCXV -> 1715
Elapsed time: 101 ms
Logic is quite simple we just go from left to right through roman literal:
if a literal isn't first and the previous one is lower -> we have to add current number to total & extract the previous number twice. First time what we added this at the previous step (when it was current number). Second because it is a rule of roman literals conversion (like IX literal).
otherwise, just add it to the total result.

How about this?
int getdec(const string& input)
{
int sum=0; char prev='%';
for(int i=(input.length()-1); i>=0; i--)
{
if(value(input[i])<sum && (input[i]!=prev))
{ sum -= value(input[i]);
prev = input[i];
}
else
{
sum += value(input[i]);
prev = input[i];
}
}
return sum;
}

Supposing Well-formed Roman numbers:
private static int totalValue(String val)
{
String aux=val.toUpperCase();
int sum=0, max=aux.length(), i=0;
while(i<max)
{
if ((i+1)<max && valueOf(aux.charAt(i+1))>valueOf(aux.charAt(i)))
{
sum+=valueOf(aux.charAt(i+1)) - valueOf(aux.charAt(i));
i+=2;
}
else
{
sum+=valueOf(aux.charAt(i));
i+=1;
}
}
return sum;
}
private static int valueOf(Character c)
{
char aux = Character.toUpperCase(c);
switch(aux)
{
case 'I':
return 1;
case 'V':
return 5;
case 'X':
return 10;
case 'L':
return 50;
case 'C':
return 100;
case 'D':
return 500;
case 'M':
return 1000;
default:
return 0;
}
}

what about this conversion. no switch, no case at all...
P.S. : I use this script from a bash shell
import sys
def RomanToNum(r):
return {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000,
}[r]
#
#
#
EOF = "<"
Roman = sys.argv[1].upper().strip()+EOF
num = 0
i = 0
while True:
this = Roman[i]
if this == EOF:
break
n1 = RomanToNum(this)
next = Roman[i+1]
if next == EOF:
n2 = 0
else:
n2 = RomanToNum(next)
if n1 < n2:
n1 = -1 * n1
num = num + n1
i = i + 1
print num

public class RomInt {
String roman;
int val;
void assign(String k)
{
roman=k;
}
private class Literal
{
public char literal;
public int value;
public Literal(char literal, int value)
{
this.literal = literal;
this.value = value;
}
}
private final Literal[] ROMAN_LITERALS = new Literal[]
{
new Literal('I', 1),
new Literal('V', 5),
new Literal('X', 10),
new Literal('L', 50),
new Literal('C', 100),
new Literal('D', 500),
new Literal('M', 1000)
};
public int getVal(String s) {
int holdValue=0;
for (int j = 0; j < ROMAN_LITERALS.length; j++)
{
if (s.charAt(0)==ROMAN_LITERALS[j].literal)
{
holdValue=ROMAN_LITERALS[j].value;
break;
} //if()
}//for()
return holdValue;
} //getVal()
public int count()
{
int count=0;
int countA=0;
int countB=0;
int lastPosition = 0;
for(int i = 0 ; i < roman.length(); i++)
{
String s1 = roman.substring(i,i+1);
int a=getVal(s1);
countA+=a;
}
for(int j=1;j<roman.length();j++)
{
String s2= roman.substring(j,j+1);
String s3= roman.substring(j-1,j);
int b=getVal(s2);
int c=getVal(s3);
if(b>c)
{
countB+=c;
}
}
count=countA-(2*countB);
return count;
}
void disp()
{
int result=count();
System.out.println("Integer equivalent of "+roman+" = " +result);
}
} //RomInt---BLC

I find the following approach a very intuitive one:
public void makeArray(String romanNumeral){
int[] numberArray = new int[romanNumeral.length()];
for(int i=0; i<romanNumeral.length();i++){
char symbol = romanNumeral.charAt(i);
switch(symbol){
case 'I':
numberArray[i] = 1;
break;
case 'V':
numberArray[i] = 5;
break;
case 'X':
numberArray[i] = 10;
break;
case 'L':
numberArray[i] = 50;
break;
case 'C':
numberArray[i] = 100;
break;
case 'D':
numberArray[i] = 500;
break;
case 'M':
numberArray[i] = 1000;
break;
}
}
calculate(numberArray);
}
public static void calculate(int[] numberArray){
int theNumber = 0;
for(int n=0;n<numberArray.length;n++){
if(n !=numberArray.length-1 && numberArray[n] < numberArray[n+1]){
numberArray[n+1] = numberArray[n+1] - numberArray[n];
numberArray[n] = 0;
}
}
for(int num:numberArray){
theNumber += num;
}
System.out.println("Converted number: " + theNumber);
}

//Bet no one has a smaller and easier logic than this........Open CHALLENGE!!!!!!!
import java.io.*;
class Convertion_practical_q2
{
void Decimal()throws IOException //Smaller code for convertion from roman to decimal
{
DataInputStream in=new DataInputStream(System.in);
System.out.println("Enter the number");
String num=in.readLine();
char pos[]={'0','I','V','X','L','C','D','M'};
int l1=7; //l1 is size of pos array
String v[]={"","1","5","10","50","100","500","1000"};
int l=num.length();
int p=0,p1=0,sum=0;
for(int i=l-1;i>=0;i--)
{
char ch=num.charAt(i);
for(int j=1;j<=l1;j++)
{
if(ch==pos[j])
p=j;
}
if(p>=p1)
sum+=Integer.parseInt(v[p]);
else
sum-=Integer.parseInt(v[p]);
//System.out.println("sum ="+sum+"\np="+p+"\np1="+p1);
p1=p;
}
System.out.println(sum);
}
}

Just got it working in Java, nice job guys.
public int getDecimal (String roman) {
int decimal = 0;
int romanNumber = 0;
int prev = 0;
for (int i = roman.length()-1; i >= 0; i--){
romanNumber = hashRomans.get(roman.charAt(i));
if(romanNumber < decimal && romanNumber != prev ){
decimal -= romanNumber;
prev = romanNumber;
} else {
decimal += romanNumber;
prev = romanNumber;
}
}
return decimal;
}

This should work:
import java.io.*;
import java.util.Scanner;
enum RomanToNumber {
i(1), v(5), x(10), l(50), c(100); int value;
RomanToNumber (int p){value = p;}
int getValue(){return value;}
}
public class RomanToInteger {
public static void main(String[] args){
RomanToNumber n;
System.out.println( "Type a valid roman number in lower case" );
String Str = new String(new Scanner(System.in).nextLine());
int n1 = 0, theNo = 0, len = Str.length();
int[] str2No = new int [len];
for(int i=0; i < len; i++){
n = RomanToNumber.valueOf(Str.substring(n1, ++n1));
str2No[i] = n.getValue();
}
for(int j = 0; j < (len-1); j++){
if( str2No[j] >= str2No[j+1] ){ theNo += str2No[j]; }
else{ theNo -= str2No[j]; }
}
System.out.println( theNo += str2No[len-1] );
}
}

Since most of the answers here are in Java, I'm posting the answer in C++ (since I am bored right now and nothing more productive to do :) But please, no downvotes except if code is wrong.
Known-issues = will not handle overflow
Code:
#include <unordered_map>
int convert_roman_2_int(string& str)
{
int ans = 0;
if( str.length() == 0 )
{
return ans;
}
std::unordered_map<char, int> table;
table['I'] = 1;
table['V'] = 5;
table['X'] = 10;
table['L'] = 50;
table['C'] = 100;
table['D'] = 500;
table['M'] = 1000;
ans = table[ str[ str.length() - 1 ] ];
for( int i = str.length() - 2; i >= 0; i--)
{
if(table[ str[i] ] < table[ str[i+1] ] )
{
ans -= table[ str[i] ];
}
else
{
ans += table[ str[i] ];
}
}
return ans;
}
// test code
void run_test_cases_convert_roman_to_int()
{
string roman = "VIII";
int r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "XX";
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "CDX"; //410
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "MCMXC"; //1990
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "MMVIII"; //2008
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "MDCLXVI"; //1666
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
}

this is very basic implementation of what you asked and working for all the test cases. If you find anything wrong in it than do mention it,i will try to make it correct also the code is in C++ .
int RomanToInt(string s){
int len = s.length();
map<char,int>mp;
int decimal = 0;
mp['I'] = 1;mp['V'] = 5;mp['X'] = 10;
mp['L'] = 50;mp['C'] = 100;mp['D'] = 500;mp['M'] = 1000;
for(int i = 0; i < len ;i++){
char cur = s[i],fast = s[i+1];
int cur_val = mp[cur],fast_val = mp[fast];
if(cur_val < fast_val){
decimal = decimal - cur_val;
}else{
decimal += cur_val;
}
}
return decimal;
}

public static int convertFromRoman(String romanNumeral)
{
Character[] rnChars = { 'M', 'D', 'C', 'L', 'X', 'V', 'I' };
int[] rnVals = { 1000, 500, 100, 50, 10, 5, 1 };
HashMap<Character, Integer> valueLookup = new HashMap<Character, Integer>();
for (int i = 0; i < rnChars.length;i++)
valueLookup.put(rnChars[i], rnVals[i]);
int retVal = 0;
for (int i = 0; i < romanNumeral.length();i++)
{
int addVal = valueLookup.get(romanNumeral.charAt(i));
retVal += i < romanNumeral.length()-1 &&
addVal < valueLookup.get(romanNumeral.charAt(i+1))?
-addVal:addVal;
}
return retVal;
}

This is a modest variation of the recursive algorithm suggested by Sahtiel:
public static int toArabic(String number) throws Exception {
String[] letras = {"M","CM","D","CD","C","XC","L","XL","X", "IX","V","IV","I"};
int[] valores = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
// here we can do even more business validations like avoiding sequences like XXXXM
if (number==null || number.isEmpty()) {
return 0;
}
for(int i=0; i<letras.length; i++) {
if (number.startsWith(letras[i])) {
return valores[i] + toArabic(number.substring(letras[i].length()));
}
}
throw new Exception("something bad happened");
}
It uses less than 10 effective lines of code.

This scala solution might be useful:
class RomanNumberConverter {
private val toArabic = Map('I' -> 1, 'V' -> 5, 'X' -> 10, 'L' -> 50, 'C' -> 100, 'D' -> 500, 'M' -> 1000)
// assume that correct roman number is provided
def convert(romanNumber: String): Int = {
def convert(rn: StringBuilder, lastDecimal: Int, acc: Int): Int = {
if (rn.isEmpty) acc
else {
val thisDecimal = toArabic(rn.head)
if (thisDecimal > lastDecimal) convert(rn.tail, thisDecimal, acc + thisDecimal - lastDecimal - lastDecimal)
else convert(rn.tail, thisDecimal, acc + thisDecimal)
}
}
val sb = new StringBuilder(romanNumber)
convert(sb.tail, toArabic(sb.head), toArabic(sb.head))
}
}

Solution using tail recursion:
import java.util.LinkedHashMap;
public class RomanNumber {
private final static LinkedHashMap<String, Integer> roman2number = new LinkedHashMap<>(); // preserve key order
static {
roman2number.put("M", 1000);
roman2number.put("CM", 900);
roman2number.put("D", 500);
roman2number.put("CD", 400);
roman2number.put("C", 100);
roman2number.put("XC", 90);
roman2number.put("L", 50);
roman2number.put("XL", 40);
roman2number.put("X", 10);
roman2number.put("IX", 9);
roman2number.put("V", 5);
roman2number.put("IV", 4);
roman2number.put("I", 1);
}
public final static Integer toDecimal(String roman) {
for (String key : roman2number.keySet()) {
if (roman.startsWith(key)) {
if (roman.equals(key)) {
return roman2number.get(key);
}
return roman2number.get(key) + toDecimal(roman.substring(key.length()));
}
}
return 0;
}
}
Testing:
import junitparams.JUnitParamsRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import junitparams.Parameters;
import static org.junit.Assert.assertTrue;
#RunWith(JUnitParamsRunner.class)
public class RomanNumberTest {
#Test
#Parameters({ "1|I", "2|II", "3|III", "4|IV", "5|V", "6|VI", "7|VII", "8|VIII", "9|IX", "10|X",
"11|XI", "12|XII", "13|XIII", "14|XIV", "15|XV", "16|XVI", "17|XVII", "18|XVIII", "19|XIX",
"20|XX", "50|L", "53|LIII", "57|LVII", "40|XL", "49|XLIX", "59|LIX", "79|LXXIX", "100|C", "90|XC", "99|XCIX",
"200|CC", "500|D", "499|CDXCIX", "999|CMXCIX", "2999|MMCMXCIX", "3999|MMMCMXCIX"
})
public void forRomanReturnsNumber(int number, String roman) {
assertTrue(roman + "->" + number, RomanNumber.toDecimal(roman) == (number));
}
}

With only two if-statements:
Check the match of first character on priority and if not matching, match the single first character.
public class Solution {
private static TreeMap<String, Integer> numeralsAndVal;
static{
numeralsAndVal = new TreeMap<>();
numeralsAndVal.put("M", 1000);
numeralsAndVal.put("CM", 900);
numeralsAndVal.put("D", 500);
numeralsAndVal.put("CD", 400);
numeralsAndVal.put("C", 100);
numeralsAndVal.put("XC", 90);
numeralsAndVal.put("L", 50);
numeralsAndVal.put("XL", 40);
numeralsAndVal.put("X", 10);
numeralsAndVal.put("IX", 9);
numeralsAndVal.put("V", 5);
numeralsAndVal.put("IV", 4);
numeralsAndVal.put("I", 1);
}
public int romanToInt(String A) {
if (A.length() == 0) return 0;
if (A.length() >= 2 && numeralsAndVal.containsKey(A.substring(0, 2))){
return numeralsAndVal.get(A.substring(0, 2)) + romanToInt(A.substring(2));
}
return numeralsAndVal.get(A.substring(0, 1)) + romanToInt(A.substring(1));
}
}

For converting TO arabic, it works as follows:
grab the rightmost unchecked character and convert it to its numeric value using the map. If this value is less than the "top" value we've seen so far, then it needs to be subtracting (e.g. IV needs to be 4, not 6), otherwise we add the value to the total and make it the new top value we've seen so far. So, for instance, XIX works like follows: 'X' is checked and comes out to be value of 10. That is higher than the "top" value seen so far, so it becomes "top" and we add 10 to the value. Then go to the next character and "I" is < 10, so subtract
public class RomanNumeral {
private final Map<Integer, String> arabicToRoman = new LinkedHashMap<Integer, String>();
private final Map<String, Integer> romanToArabic = new LinkedHashMap<String, Integer>();
public RomanNumeral() {
arabicToRoman.put(10, "X");
arabicToRoman.put(9, "IX");
arabicToRoman.put(5, "V");
arabicToRoman.put(4, "IV");
arabicToRoman.put(1, "I");
romanToArabic.put("X", 10);
romanToArabic.put("V", 5);
romanToArabic.put("I", 1);
}
public String convertToRomanNumeral(int number) {
String result = "";
for (Integer i : arabicToRoman.keySet()) {
while (number >= i) {
result += arabicToRoman.get(i);
number -= i;
}
}
return result;
}
public String convertToArabicNumber(String romanNumeral) {
int result = 0;
int top = 0;
for (int i = romanNumeral.length() - 1; i >= 0; i--) {
char current = romanNumeral.charAt(i);
int value = romanToArabic.get("" + current);
if (value < top) {
result -= value;
} else {
result += value;
top = value;
}
}
return "" + result;
}
}

An easy solution for input in the range from 1 to 3999.
private static final Map<String, Integer> MAPPING = new HashMap<>() {{
put("I", 1);
put("V", 5);
put("X", 10);
put("L", 50);
put("C", 100);
put("D", 500);
put("M", 1000);
put("IV", 4);
put("IX", 9);
put("XL", 40);
put("XC", 90);
put("CD", 400);
put("CM", 900);
}};
public static int romanToInt(String s) {
int sum = 0;
for (int i = 0; i < s.length(); i++) {
if (i < s.length() - 1 && MAPPING.containsKey(String.valueOf(s.charAt(i)) + s.charAt(i + 1))) {
sum += MAPPING.get(String.valueOf(s.charAt(i)) + s.charAt(i + 1));
i++;
} else {
sum += MAPPING.get(String.valueOf(s.charAt(i)));
}
}
return sum;
}

The problem here is that numbers like 9 are presented in the following way
IX = 9
if we take the literal conversion by getting the sum for each number than our program would give us the following sum
I = 1
X = 10
X + I = 11
which is not correct.
We can overcome this if we simply manipulate the Roman String.
In example:
IX = 9 would be VIIII which is 5 + 1 + 1 + 1 + 1
Therefore if we replace all the special cases in the given String, we can calculate the sum for each character.
Hence;
class Solution {
public int romanToInt(String s) {
// Key Value pairs
Map<Character, Integer> map = new HashMap<>();
map.put('I', 1);
map.put('V', 5);
map.put('X', 10);
map.put('L', 50);
map.put('C', 100);
map.put('D', 500);
map.put('M', 1000);
// convert these to single characters
s = s.replace("IV","IIII");
s = s.replace("IX","VIIII");
s = s.replace("XL","XXXX");
s = s.replace("XC","LXXXX");
s = s.replace("CD","CCCC");
s = s.replace("CM","DCCCC");
// total sum to be returned
int sum = 0;
// convert s to c character array
char[] c = s.toCharArray();
// iterate through c array and sum the numbers
for(Character ch : c){
sum = sum + map.get(ch);
}
return sum;
}
}

Here is my one...
import java.util.Scanner;
class Solution {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
String num;
// System.out.println("enter the number you want to convert from roman to integer.");
num = "D";
System.out.println("length of string is " + num.length());
System.out.println("the integer number is :" + romanToInt(num) );
}
public static int romanToInt(String s) {
char I,V, X, L,C, D, M;
char c1,c3, c2 = s.charAt(0);
// System.out.println("the c2 is : " + (int)c2);
int num = 0, num1 = 0;
int j =0, k = 0, temp = 0;
if (c2 == 'I') {
k = (int)c2 - 72;
System.out.println("k is I" + k);
} else if(c2 == 'V') {
k = (int)c2 - 81;
System.out.println("K is V" + k);
// return 86 - 81;
} else if (c2 == 'X') {
k = (int)c2 - 78;
System.out.println("K is X" + k);
} else if (c2 == 'L') {
k = (int)c2 - 26;
System.out.println("K is L" + k);
} else if (c2 == 'C') {
k = (int)c2 + 33;
System.out.println("K is C" + k);
} else if (c2 == 'D') {
k = (int)c2 + 432;
System.out.println("K is D" + k);
} else if ( c2 == 'M') {
k = (int)c2 + 923;
System.out.println("K is M" + k);
}
if (s.length() == 1){
num = k;
} else {
for(int i = 1; i<= s.length()-1 ; i++) {
System.out.println("i is : " + i);
c1 = s.charAt(i);
if (i == s.length() - 1) {
temp = 0;
} else {
c3 = s.charAt(i+1);
if (c3 == 'I') {
temp = (int)c3 - 72;
System.out.println("temp is I " + temp);
} else if(c3 == 'V') {
temp = (int)c3 - 81;
System.out.println("temp is I " + temp);
// return 86 - 81;
} else if (c3 == 'X') {
temp = (int)c3 - 78;
System.out.println("temp is I " + temp);
} else if (c3 == 'L') {
temp = (int)c3 - 26;
System.out.println("temp is I " + temp);
} else if (c3 == 'C') {
temp = (int)c3 + 33;
System.out.println("temp is I " + temp);
} else if (c3 == 'D') {
temp = (int)c3 + 432;
System.out.println("temp is I " + temp);
} else if ( c3 == 'M') {
temp = (int)c3 + 923;
System.out.println("temp is I " + temp);
}
}
if (c1 == 'I') {
j = (int)c1 - 72;
System.out.println("j is I " + j);
} else if(c1 == 'V') {
j = (int)c1 - 81;
System.out.println("j is V " + j);
// return 86 - 81;
} else if (c1 == 'X') {
j = (int)c1 - 78;
System.out.println("j is X " + j);
} else if (c1 == 'L') {
j = (int)c1 - 26;
System.out.println("j is L " + j);
} else if (c1 == 'C') {
j = (int)c1 + 33;
System.out.println("j is C " + j);
} else if (c1 == 'D') {
j = (int)c1 + 432;
System.out.println("j is D " + j);
} else if ( c1 == 'M') {
j = (int)c1 + 923;
System.out.println("j is M " + j);
}
if ( k < j && j>temp ) {
k = j - k ;
num = num + k;
} else if (j==k || j<k || j<temp){
num = num + k ;
// k = j;
}
if (j>k ) {
k = temp;
i += 1;
if (i == s.length()-1) {
num = num + k;
}
} else {
k = j;
if (i == s.length()-1) {
num = num + k;
}
}
}
}
return num;
}
}

Related

How to enable my program to receive small to extensive, large numbers > 2.14 billion

I'm currently coding a program that converts a number to its word format, and thus far, I've written a code that only accepts no larger than the max value of an integer (2.14 billion). I was wondering how I would scale up the program's capability to accepting larger numbers.
(Edited): I've converted all my int values to long datatypes. I was able to scale the limitation up from 2.14 to 999 billion, though shouldn't be the max value of a long datatype is 9 quintillion?
The converter code:
public class Converter {
public static WordList wordFormat = new WordList();
public static final void converter(long value) {
long valueSize = String.valueOf(value).length();
String[] output = new String[(int) valueSize];
long outputSize = output.length;
long tracker = 1;
long commasCTR = 0;
long preValHolder = 0;
// Returns "Zero" if value = 0
if (value == 0) {
System.out.println("Zero");
return;
};
// Self-made Conversion Method
for (long valHolder = value, placeVal = 0; placeVal <= outputSize - 1; placeVal++, tracker++) {
long remainder = valHolder % 10;
long nextDigit = valHolder / 10 % 10;
valHolder = valHolder / 10;
// Num to Word Conditional Statements
switch ((int) tracker) {
case 1:
if (placeVal == 0) {
output[(int) placeVal] = WordList.wordFormat[0][(int) remainder]; // Ones
} else {
output[(int) placeVal] = WordList.wordFormat[0][(int) remainder].concat(" " + WordList.commas[(int) commasCTR]); // Commas
commasCTR++;
}
break;
case 2:
if (remainder == 1) { // Teens
output[(int) placeVal] = WordList.wordFormat[1][(int) preValHolder + 1];
if (placeVal < 3) output[(int) placeVal - 1] = " ";
else output[(int) placeVal - 1] = WordList.commas[(int) commasCTR - 1];
} else if (placeVal > 3 && preValHolder == 0 && remainder == 0 && nextDigit == 0) { // Comma Zero Value Handler
output[(int) placeVal - 1] = " ";
output[(int) placeVal] = WordList.wordFormat[2][(int) remainder];
} else {
output[(int) placeVal] = WordList.wordFormat[2][(int) remainder]; // Decades
}
break;
case 3:
output[(int) placeVal] = WordList.wordFormat[3][(int) remainder]; // Hundredths
break;
}
// Re-assigning Values
if (tracker == 3) tracker = 0;
preValHolder = remainder;
}
for (long i = outputSize - 1; i >= 0; i--) {
if (output[(int) i] == " ") continue;
System.out.print(output[(int) i].trim() + " ");
}
return;
}
}
}```
I think you could use BigInteger https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html

The smallest Palindrome number is greater N

For a given positive integer N of not more than 1000000 digits, write the value of the smallest palindrome larger than N to output.
Here is my code:
public class Palin {
public static String reverseString(String s) {
String newS = "";
for(int i = s.length() - 1; i >= 0; i--)
newS += s.charAt(i);
return newS;
}
public static String getPalin(String s) {
int lth = s.length();
String left = "", mid = "", right = "", newS = "";
if(lth % 2 != 0) {
left = s.substring(0, lth / 2);
mid = s.substring(lth / 2, lth / 2 + 1);
right = reverseString(left);
newS = left + mid + right;
if(s.compareTo(newS) < 0) return newS;
else {
int temp = Integer.parseInt(mid);
temp++;
mid = Integer.toString(temp);
newS = left + mid + right;
return newS;
}
}
else {
left = s.substring(0, lth / 2 - 1);
mid = s.substring(lth / 2 - 1, lth / 2);
right = reverseString(left);
newS = left + mid + mid + right;
if(s.compareTo(newS) < 0) return newS;
else {
int temp = Integer.parseInt(mid);
temp++;
mid = Integer.toString(temp);
newS = left + mid + mid + right;
return newS;
}
}
}
public static void main(String[] args) throws java.lang.Exception {
Scanner input = new Scanner(System.in);
//Scanner input = new Scanner(System.in);
int k = input.nextInt();
String[] s = new String[k];
for(int i = 0; i < k; i++) {
s[i] = input.next();
}
for(int i = 0; i < k; i++) {
System.out.println(getPalin(s[i]));
}
}
}
My idea is use a String represent for a number. I divide this String into 2 part, coppy first part and reverse it for second part. I think my solve is correct but it not fast enough. I need a more efficient algorithm.
Thanks
EDITED
Since you said that:
For a given positive integer N of not more than 1000000 digits
My previous solution won't work since I have converted them to int and an int can't accommodate 1000000 digits. Thus I have made a new approach, an approach that doesn't need any String to int conversion.
Refer to the code and comment below for details.
CODE:
package main;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Scanner input = new Scanner(System.in);
int k = Integer.parseInt(input.nextLine());
String[] s = new String[k];
for (int i = 0; i < k; i++) {
s[i] = input.nextLine();
}
for (int i = 0; i < k; i++) {
System.out.println(getPalin(s[i]));
}
input.close();
}
public static String getPalin(String s) {
// initialize the result to "" since if input is 1 digit, nothing is printed
String result = "";
// if input is greater than 1000000 digits
if (s.length() >= 1000000) {
// return the highest palindrome less than 1000000
result = "999999";
} else if (s.length() > 1) {
// get the middle index of the string
int mid = s.length() % 2 == 0 ? s.length() / 2 : (s.length() / 2) + 1;
// get the left part of the string
String leftPart = getPalindrome(s.substring(0, mid));
if (s.length() % 2 == 0) {
// attach the left part and the reverse left part
result = leftPart + new StringBuilder(leftPart).reverse().toString();
} else {
// attach the left part and the reverse left part excluding the middle digit
result = leftPart
+ new StringBuilder(leftPart.substring(0, leftPart.length() - 1)).reverse().toString();
}
// check if the new result greater than 1000000 digits
if (result.length() >= 1000000) {
// return the highest palindrome less than 1000000
result = "999999";
}
}
return result;
}
public static String getPalindrome(String param) {
String result = "";
// iterate through the string from last index until index 0
for (int i = param.length() - 1; i >= 0; i--) {
// get the char at index i
char c = param.charAt(i);
/*
* increment char since the next palindrome is the current digit + 1. Example:
* User input is 121, then param will be 12 so the next is 13
*/
c++;
/*
* check if the current character is greater than '9', which means it is not a
* digit after incrementing
*/
if (c > '9') {
// set the current char to 0
c = '0';
// check if index is at index 0
if (i - 1 < 0) {
// if at index 0 then add '1' at start
result = '1' + result;
} else {
// if not then append c at result
result = result + c;
}
} else {
// check if index is at index 0
if (i - 1 < 0) {
// if not then prepend c at result
result = c + result;
} else {
// if not then get the rest of param then append c and result
result = param.substring(0, i) + c + result;
}
break;
}
}
return result;
}
}

Converting binary string to a hexadecimal string JAVA

I want to convert my binary(which is in string) to hexadecimal string also, this is just a program fragment since this program is just a part of another bigger program:
//the variable name of the binary string is: "binary"
int digitNumber = 1;
int sum = 0;
int test = binary.length()%4;
if(test!=0) {
binary = padLeft(binary, test);
}
for(int i = 0; i < binary.length(); i++){
if(digitNumber == 1)
sum+=Integer.parseInt(binary.charAt(i) + "")*8;
else if(digitNumber == 2)
sum+=Integer.parseInt(binary.charAt(i) + "")*4;
else if(digitNumber == 3)
sum+=Integer.parseInt(binary.charAt(i) + "")*2;
else if(digitNumber == 4 || i < binary.length()+1){
sum+=Integer.parseInt(binary.charAt(i) + "")*1;
digitNumber = 0;
if(sum < 10)
System.out.print(sum);
else if(sum == 10)
System.out.print("A");
else if(sum == 11)
System.out.print("B");
else if(sum == 12)
System.out.print("C");
else if(sum == 13)
System.out.print("D");
else if(sum == 14)
System.out.print("E");
else if(sum == 15)
System.out.print("F");
sum=0;
}
digitNumber++;
}
public static String padLeft(String s, int n) {
return String.format("%0$"+n+"s", s);
}//i added this for padding
the problem is that i dont know if the padding works but i am sure that this program return a wrong hexadecimal conversion of the binary string I am trying to do this:
http://www.wikihow.com/Convert-Binary-to-Hexadecimal
PS: I need to implement it(not using any built-in function)
If you don't have to implement that conversion yourself, you can use existing code :
int decimal = Integer.parseInt(binaryStr,2);
String hexStr = Integer.toString(decimal,16);
If you must implement it yourself, there are several problems in your code :
The loop should iterate from 0 to binary.length()-1 (assuming the first character of the String represents the most significant bit).
You implicitly assume that your binary String has 4*x charcters for some integer x. If that's not true, your algorithm breaks. You should left pad your String with zeroes to get a String of such length.
sum must be reset to 0 after each hex digit you output.
System.out.print(digitNumber); - here you should print sum, not digitNumber.
Here's how the mostly fixed code looks :
int digitNumber = 1;
int sum = 0;
String binary = "011110101010";
for(int i = 0; i < binary.length(); i++){
if(digitNumber == 1)
sum+=Integer.parseInt(binary.charAt(i) + "")*8;
else if(digitNumber == 2)
sum+=Integer.parseInt(binary.charAt(i) + "")*4;
else if(digitNumber == 3)
sum+=Integer.parseInt(binary.charAt(i) + "")*2;
else if(digitNumber == 4 || i < binary.length()+1){
sum+=Integer.parseInt(binary.charAt(i) + "")*1;
digitNumber = 0;
if(sum < 10)
System.out.print(sum);
else if(sum == 10)
System.out.print("A");
else if(sum == 11)
System.out.print("B");
else if(sum == 12)
System.out.print("C");
else if(sum == 13)
System.out.print("D");
else if(sum == 14)
System.out.print("E");
else if(sum == 15)
System.out.print("F");
sum=0;
}
digitNumber++;
}
Output :
7AA
This will work only if the number of binary digits is divisable by 4, so you must add left 0 padding as a preliminray step.
Use this for any binary string length:
String hexString = new BigInteger(binaryString, 2).toString(16);
You can try something like this.
private void bitsToHexConversion(String bitStream){
int byteLength = 4;
int bitStartPos = 0, bitPos = 0;
String hexString = "";
int sum = 0;
// pad '0' to make input bit stream multiple of 4
if(bitStream.length()%4 !=0){
int tempCnt = 0;
int tempBit = bitStream.length() % 4;
while(tempCnt < (byteLength - tempBit)){
bitStream = "0" + bitStream;
tempCnt++;
}
}
// Group 4 bits, and find Hex equivalent
while(bitStartPos < bitStream.length()){
while(bitPos < byteLength){
sum = (int) (sum + Integer.parseInt("" + bitStream.charAt(bitStream.length()- bitStartPos -1)) * Math.pow(2, bitPos)) ;
bitPos++;
bitStartPos++;
}
if(sum < 10)
hexString = Integer.toString(sum) + hexString;
else
hexString = (char) (sum + 55) + hexString;
bitPos = 0;
sum = 0;
}
System.out.println("Hex String > "+ hexString);
}
Hope this helps :D
import java.util.*;
public class BinaryToHexadecimal
{
public static void main()
{
Scanner sc=new Scanner(System.in);
System.out.println("enter the binary number");
double s=sc.nextDouble();
int c=0;
long s1=0;
String z="";
while(s>0)
{
s1=s1+(long)(Math.pow(2,c)*(long)(s%10));
s=(long)s/10;
c++;
}
while(s1>0)
{
long j=s1%16;
if(j==10)
{
z="A"+z;
}
else if(j==11)
{
z="B"+z;
}
else if(j==12)
{
z="C"+z;
}
else if(j==13)
{
z="D"+z;
}
else if(j==14)
{
z="E"+z;
}
else if(j==15)
{
z="F"+z;
}
else
{
z=j+z;
}
s1=s1/16;
}
System.out.println("The respective Hexadecimal number is : "+z);
}
}
By given binary number 01011011, we will convert it at first to decimal number, each number will be Math.pow() by decrementd length:
01011011 =(0 × 2(7)) + (1 × 2(6)) + (0 × 2(5)) + (1 × 2(4)) + (1 × 2(3)) + (0 × 2(2)) + (1 × 2(1)) + (1 × 2(0))
= (0 × 128) + (1 × 64) + (0 × 32) + (1 × 16) + (1 × 8) + (0 × 4) + (1 × 2) + (1 × 1)
= 0 + 64 + 0 + 16 + 8 + 0 + 2 + 1
= 91 (decimal form of binary number)
Now after get decimal number we have to convert it to hexa-decimal-number.
So, 91 is greater than 16. So, we have to divide by 16.
After dividing by 16, quotient is 5 and remainder is 11.
Remainder is less than 16.
Hexadecimal number of remainder is B.
Quotient is 5 and hexadecimal number of remainder is B.
That is, 91 = 16 × 5 +11 = B
5 = 16 × 0 + 5 = 5
=5B
Implementation:
String hexValue = binaryToHex(binaryValue);
//Display result
System.out.println(hexValue);
private static String binaryToHex(String binary) {
int decimalValue = 0;
int length = binary.length() - 1;
for (int i = 0; i < binary.length(); i++) {
decimalValue += Integer.parseInt(binary.charAt(i) + "") * Math.pow(2, length);
length--;
}
return decimalToHex(decimalValue);
}
private static String decimalToHex(int decimal){
String hex = "";
while (decimal != 0){
int hexValue = decimal % 16;
hex = toHexChar(hexValue) + hex;
decimal = decimal / 16;
}
return hex;
}
private static char toHexChar(int hexValue) {
if (hexValue <= 9 && hexValue >= 0)
return (char)(hexValue + '0');
else
return (char)(hexValue - 10 + 'A');
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stringprocessing;
/**
*
* #author Zayeed Chowdhury
*/
public class StringProcessing {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int index = 0;
String bin = "0000000101100101011011100110011100000001000000000000000010101010010101100110010101100011011010010110110101100001001000000100111001100101011101000111011101101111011100100110101101110011001000000100100001000001010100110010000001001001010100110101001101010101010001010100010000100000010000010010000001010010010001010101000101010101010010010101001001000101010001000010000001010111010001010100010101001011010011000101100100100000010101000100010101010011010101000010000001000110010011110101001000100000010101000100100001000101001000000100011001001111010011000100110001001111010101110100100101001110010001110010000001000011010011110101010101001110010101000100100101000101010100110010111101000001010100100100010101000001010100110011101000100000010100000110100101101110011000010110110000101100001000000100000101011010001110110010000001000001010101000010000000000001111000000011000100110010001110100011000100110011001000000101000001001101001000000100111101001110";
String[] hexString = new String[bin.length() / 4];
for (int i = 0; i < bin.length() / 4; i++) {
hexString[i] = "";
for (int j = index; j < index + 4; j++) {
hexString[i] += bin.charAt(j);
}
index += 4;
}
for (int i = 0; i < bin.length() / 4; i++) {
System.out.print(hexString[i] + " ");
}
System.out.println("\n" + bin.length());
String[] result = binaryToHex(hexString);
for (int i = 0; i < result.length; i++) {
System.out.print("" + result[i].toUpperCase());
}
System.out.println("");
}
public static String[] binaryToHex(String[] bin) {
String[] result = new String[bin.length];
for (int i = 0; i < bin.length; i++) {
result[i] = Integer.toHexString(Integer.parseInt(bin[i], 2));
}
//return Integer.toHexString(Integer.parseInt(bin[0], 2));
return result;
}
}
private final String[] hexValues = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
public void binaryToHexadecimal(String binary){
String hexadecimal;
binary = leftPad(binary);
System.out.println(convertBinaryToHexadecimal(binary));
}
public String convertBinaryToHexadecimal(String binary){
String hexadecimal = "";
int sum = 0;
int exp = 0;
for (int i=0; i<binary.length(); i++){
exp = 3 - i%4;
if((i%4)==3){
sum = sum + Integer.parseInt(binary.charAt(i)+"")*(int)(Math.pow(2,exp));
hexadecimal = hexadecimal + hexValues[sum];
sum = 0;
}
else
{
sum = sum + Integer.parseInt(binary.charAt(i)+"")*(int)(Math.pow(2,exp));
}
}
return hexadecimal;
}
public String leftPad(String binary){
int paddingCount = 0;
if ((binary.length()%4)>0)
paddingCount = 4-binary.length()%4;
while(paddingCount>0) {
binary = "0" + binary;
paddingCount--;
}
return binary;
}

Check Credit Card Validity using Luhn Algorithm

I tried to check the validation of credit card using Luhn algorithm, which works as the following steps:
Double every second digit from right to left. If doubling of a digit results in a two-digit number, add up the two digits to get a single-digit number.
2 * 2 = 4
2 * 2 = 4
4 * 2 = 8
1 * 2 = 2
6 * 2 = 12 (1 + 2 = 3)
5 * 2 = 10 (1 + 0 = 1)
8 * 2 = 16 (1 + 6 = 7)
4 * 2 = 8
Now add all single-digit numbers from Step 1.
4 + 4 + 8 + 2 + 3 + 1 + 7 + 8 = 37
Add all digits in the odd places from right to left in the card number.
6 + 6 + 0 + 8 + 0 + 7 + 8 + 3 = 38
Sum the results from Step 2 and Step 3.
37 + 38 = 75
If the result from Step 4 is divisible by 10, the card number is valid; otherwise, it is invalid. For example, the number 4388576018402626 is invalid, but the number 4388576018410707 is valid.
Simply, my program always displays valid for everything that I input. Even if it's a valid number and the result of sumOfOddPlace and sumOfDoubleEvenPlace methods are equal to zero. Any help is appreciated.
import java.util.Scanner;
public class CreditCardValidation {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int count = 0;
long array[] = new long [16];
do
{
count = 0;
array = new long [16];
System.out.print("Enter your Credit Card Number : ");
long number = in.nextLong();
for (int i = 0; number != 0; i++) {
array[i] = number % 10;
number = number / 10;
count++;
}
}
while(count < 13);
if ((array[count - 1] == 4) || (array[count - 1] == 5) || (array[count - 1] == 3 && array[count - 2] == 7)){
if (isValid(array) == true) {
System.out.println("\n The Credit Card Number is Valid. ");
} else {
System.out.println("\n The Credit Card Number is Invalid. ");
}
} else{
System.out.println("\n The Credit Card Number is Invalid. ");
}
}
public static boolean isValid(long[] array) {
int total = sumOfDoubleEvenPlace(array) + sumOfOddPlace(array);
if ((total % 10 == 0)) {
for (int i=0; i< array.length; i++){
System.out.println(array[i]);}
return true;
} else {
for (int i=0; i< array.length; i++){
System.out.println(array[i]);}
return false;
}
}
public static int getDigit(int number) {
if (number <= 9) {
return number;
} else {
int firstDigit = number % 10;
int secondDigit = (int) (number / 10);
return firstDigit + secondDigit;
}
}
public static int sumOfOddPlace(long[] array) {
int result = 0;
for (int i=0; i< array.length; i++)
{
while (array[i] > 0) {
result += (int) (array[i] % 10);
array[i] = array[i] / 100;
}}
System.out.println("\n The sum of odd place is " + result);
return result;
}
public static int sumOfDoubleEvenPlace(long[] array) {
int result = 0;
long temp = 0;
for (int i=0; i< array.length; i++){
while (array[i] > 0) {
temp = array[i] % 100;
result += getDigit((int) (temp / 10) * 2);
array[i] = array[i] / 100;
}
}
System.out.println("\n The sum of double even place is " + result);
return result;
}
}
You can freely import the following code:
public class Luhn
{
public static boolean Check(String ccNumber)
{
int sum = 0;
boolean alternate = false;
for (int i = ccNumber.length() - 1; i >= 0; i--)
{
int n = Integer.parseInt(ccNumber.substring(i, i + 1));
if (alternate)
{
n *= 2;
if (n > 9)
{
n = (n % 10) + 1;
}
}
sum += n;
alternate = !alternate;
}
return (sum % 10 == 0);
}
}
Link reference: https://github.com/jduke32/gnuc-credit-card-checker/blob/master/CCCheckerPro/src/com/gnuc/java/ccc/Luhn.java
Google and Wikipedia are your friends. Instead of long-array I would use int-array. On Wikipedia following java code is published (together with detailed explanation of Luhn algorithm):
public static boolean check(int[] digits) {
int sum = 0;
int length = digits.length;
for (int i = 0; i < length; i++) {
// get digits in reverse order
int digit = digits[length - i - 1];
// every 2nd number multiply with 2
if (i % 2 == 1) {
digit *= 2;
}
sum += digit > 9 ? digit - 9 : digit;
}
return sum % 10 == 0;
}
You should work on your input processing code. I suggest you to study following solution:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
boolean repeat;
List<Integer> digits = new ArrayList<Integer>();
do {
repeat = false;
System.out.print("Enter your Credit Card Number : ");
String input = in.next();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c < '0' || c > '9') {
repeat = true;
digits.clear();
break;
} else {
digits.add(Integer.valueOf(c - '0'));
}
}
} while (repeat);
int[] array = new int[digits.size()];
for (int i = 0; i < array.length; i++) {
array[i] = Integer.valueOf(digits.get(i));
}
boolean valid = check(array);
System.out.println("Valid: " + valid);
}
I took a stab at this with Java 8:
public static boolean luhn(String cc) {
final boolean[] dbl = {false};
return cc
.chars()
.map(c -> Character.digit((char) c, 10))
.map(i -> ((dbl[0] = !dbl[0])) ? (((i*2)>9) ? (i*2)-9 : i*2) : i)
.sum() % 10 == 0;
}
Add the line
.replaceAll("\\s+", "")
Before
.chars()
If you want to handle whitespace.
Seems to produce identical results to
return LuhnCheckDigit.LUHN_CHECK_DIGIT.isValid(cc);
From Apache's commons-validator.
There are two ways to split up your int into List<Integer>
Use %10 as you are using and store it into a List
Convert to a String and then take the numeric values
Here are a couple of quick examples
public static void main(String[] args) throws Exception {
final int num = 12345;
final List<Integer> nums1 = splitInt(num);
final List<Integer> nums2 = splitString(num);
System.out.println(nums1);
System.out.println(nums2);
}
private static List<Integer> splitInt(int num) {
final List<Integer> ints = new ArrayList<>();
while (num > 0) {
ints.add(0, num % 10);
num /= 10;
}
return ints;
}
private static List<Integer> splitString(int num) {
final List<Integer> ints = new ArrayList<>();
for (final char c : Integer.toString(num).toCharArray()) {
ints.add(Character.getNumericValue(c));
}
return ints;
}
I'll use 5 digit card numbers for simplicity. Let's say your card number is 12345; if I read the code correctly, you store in array the individual digits:
array[] = {1, 2, 3, 4, 5}
Since you already have the digits, in sumOfOddPlace you should do something like
public static int sumOfOddPlace(long[] array) {
int result = 0;
for (int i = 1; i < array.length; i += 2) {
result += array[i];
}
return result;
}
And in sumOfDoubleEvenPlace:
public static int sumOfDoubleEvenPlace(long[] array) {
int result = 0;
for (int i = 0; i < array.length; i += 2) {
result += getDigit(2 * array[i]);
}
return result;
}
this is the luhn algorithm implementation which I use for only 16 digit Credit Card Number
if(ccnum.length()==16){
char[] c = ccnum.toCharArray();
int[] cint = new int[16];
for(int i=0;i<16;i++){
if(i%2==1){
cint[i] = Integer.parseInt(String.valueOf(c[i]))*2;
if(cint[i] >9)
cint[i]=1+cint[i]%10;
}
else
cint[i] = Integer.parseInt(String.valueOf(c[i]));
}
int sum=0;
for(int i=0;i<16;i++){
sum+=cint[i];
}
if(sum%10==0)
result.setText("Card is Valid");
else
result.setText("Card is Invalid");
}else
result.setText("Card is Invalid");
If you want to make it use on any number replace all 16 with your input number length.
It will work for Visa number given in the question.(I tested it)
Here's my implementation of the Luhn Formula.
/**
* Runs the Luhn Equation on a user inputed CCN, which in turn
* determines if it is a valid card number.
* #param c A user inputed CCN.
* #param cn The check number for the card.
* #return If the card is valid based on the Luhn Equation.
*/
public boolean luhn (String c, char cn)
{
String card = c;
String checkString = "" + cn;
int check = Integer.valueOf(checkString);
//Drop the last digit.
card = card.substring(0, ( card.length() - 1 ) );
//Reverse the digits.
String cardrev = new StringBuilder(card).reverse().toString();
//Store it in an int array.
char[] cardArray = cardrev.toCharArray();
int[] cardWorking = new int[cardArray.length];
int addedNumbers = 0;
for (int i = 0; i < cardArray.length; i++)
{
cardWorking[i] = Character.getNumericValue( cardArray[i] );
}
//Double odd positioned digits (which are really even in our case, since index starts at 0).
for (int j = 0; j < cardWorking.length; j++)
{
if ( (j % 2) == 0)
{
cardWorking[j] = cardWorking[j] * 2;
}
}
//Subtract 9 from digits larger than 9.
for (int k = 0; k < cardWorking.length; k++)
{
if (cardWorking[k] > 9)
{
cardWorking[k] = cardWorking[k] - 9;
}
}
//Add all the numbers together.
for (int l = 0; l < cardWorking.length; l++)
{
addedNumbers += cardWorking[l];
}
//Finally, check if the number we got from adding all the other numbers
//when divided by ten has a remainder equal to the check number.
if (addedNumbers % 10 == check)
{
return true;
}
else
{
return false;
}
}
I pass in the card as c which I get from a Scanner and store in card, and for cn I pass in checkNumber = card.charAt( (card.length() - 1) );.
Okay, this can be solved with a type conversions to string and some Java 8
stuff. Don't forget numbers and the characters representing numbers are not the same. '1' != 1
public static int[] longToIntArray(long cardNumber){
return Long.toString(cardNumber).chars()
.map(x -> x - '0') //converts char to int
.toArray(); //converts to int array
}
You can now use this method to perform the luhn algorithm:
public static int luhnCardValidator(int cardNumbers[]) {
int sum = 0, nxtDigit;
for (int i = 0; i<cardNumbers.length; i++) {
if (i % 2 == 0)
nxtDigit = (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : nxtDigit * 2;
sum += nxtDigit;
}
return (sum % 10);
}
private static int luhnAlgorithm(String number){
int n=0;
for(int i = 0; i<number.length(); i++){
int x = Integer.parseInt(""+number.charAt(i));
n += (x*Math.pow(2, i%2))%10;
if (x>=5 && i%2==1) n++;
}
return n%10;
}
public class Creditcard {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
String cardno = sc.nextLine();
if(checkType(cardno).equals("U")) //checking for unknown type
System.out.println("UNKNOWN");
else
checkValid(cardno); //validation
}
private static String checkType(String S)
{
int AM=Integer.parseInt(S.substring(0,2));
int D=Integer.parseInt(S.substring(0,4)),d=0;
for(int i=S.length()-1;i>=0;i--)
{
if(S.charAt(i)==' ')
continue;
else
d++;
}
if((AM==34 || AM==37) && d==15)
System.out.println("AMEX");
else if(D==6011 && d==16)
System.out.println("Discover");
else if(AM>=51 && AM<=55 && d==16)
System.out.println("MasterCard");
else if(((S.charAt(0)-'0')==4)&&(d==13 || d==16))
System.out.println("Visa");
else
return "U";
return "";
}
private static void checkValid(String S) // S--> cardno
{
int i,d=0,sum=0,card[]=new int[S.length()];
for(i=S.length()-1;i>=0;i--)
{
if(S.charAt(i)==' ')
continue;
else
card[d++]=S.charAt(i)-'0';
}
for(i=0;i<d;i++)
{
if(i%2!=0)
{
card[i]=card[i]*2;
if(card[i]>9)
sum+=digSum(card[i]);
else
sum+=card[i];
}
else
sum+=card[i];
}
if(sum%10==0)
System.out.println("Valid");
else
System.out.println("Invalid");
}
public static int digSum(int n)
{
int sum=0;
while(n>0)
{
sum+=n%10;
n/=10;
}
return sum;
}
}
Here is the implementation of Luhn algorithm.
public class LuhnAlgorithm {
/**
* Returns true if given card number is valid
*
* #param cardNum Card number
* #return true if card number is valid else false
*/
private static boolean checkLuhn(String cardNum) {
int cardlength = cardNum.length();
int evenSum = 0, oddSum = 0, sum;
for (int i = cardlength - 1; i >= 0; i--) {
System.out.println(cardNum.charAt(i));
int digit = Character.getNumericValue(cardNum.charAt(i));
if (i % 2 == 0) {
int multiplyByTwo = digit * 2;
if (multiplyByTwo > 9) {
/* Add two digits to handle cases that make two digits after doubling */
String mul = String.valueOf(multiplyByTwo);
multiplyByTwo = Character.getNumericValue(mul.charAt(0)) + Character.getNumericValue(mul.charAt(1));
}
evenSum += multiplyByTwo;
} else {
oddSum += digit;
}
}
sum = evenSum + oddSum;
if (sum % 10 == 0) {
System.out.println("valid card");
return true;
} else {
System.out.println("invalid card");
return false;
}
}
public static void main(String[] args) {
String cardNum = "4071690065031703";
System.out.println(checkLuhn(cardNum));
}
}
public class LuhnAlgorithm {
/**
* Returns true if given card number is valid
*
* #param cardNum Card number
* #return true if card number is valid else false
*/
private static boolean checkLuhn(String cardNum) {
int cardlength = cardNum.length();
int evenSum = 0, oddSum = 0, sum;
for (int i = cardlength - 1; i >= 0; i--) {
System.out.println(cardNum.charAt(i));
int digit = Character.getNumericValue(cardNum.charAt(i));
if (i % 2 == 0) {
int multiplyByTwo = digit * 2;
if (multiplyByTwo > 9) {
/* Add two digits to handle cases that make two digits after doubling */
String mul = String.valueOf(multiplyByTwo);
multiplyByTwo = Character.getNumericValue(mul.charAt(0)) + Character.getNumericValue(mul.charAt(1));
}
evenSum += multiplyByTwo;
} else {
oddSum += digit;
}
}
sum = evenSum + oddSum;
if (sum % 10 == 0) {
System.out.println("valid card");
return true;
} else {
System.out.println("invalid card");
return false;
}
}
public static void main(String[] args) {
String cardNum = "8112189875";
System.out.println(checkLuhn(cardNum));
}
}
Hope it may works.
const options = {
method: 'GET',
headers: {Accept: 'application/json', 'X-Api-Key': '[APIkey]'}
};
fetch('https://api.epaytools.com/Tools/luhn?number=[CardNumber]&metaData=true', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));

Converting some hexadecimal string to a decimal integer

I wrote some code to convert my hexadecimal display string to decimal integer. However, when input is something like 100a or 625b (something with a letter) I got an error like this:
java.lang.NumberFormatException: For input string: " 100a" at
java.lang.NumberFormatException.forInputString(Unknown Source) at
java.lang.Integer.parseInt(Unknown Source)
How can I convert my string with letters to a decimal integer?
if(display.getText() != null)
{
if(display.getText().contains("a") || display.getText().contains("b") ||
display.getText().contains("c") || display.getText().contains("d") ||
display.getText().contains("e") || display.getText().contains("f"))
{
temp1 = Integer.parseInt(display.getText(), 16);
temp1 = (double) temp1;
}
else
{
temp1 = Double.parseDouble(String.valueOf(display.getText()));
}
}
It looks like there's an extra (leading) space character in your string (" 100a"). You can use trim() to remove leading and trailing whitespaces:
temp1 = Integer.parseInt(display.getText().trim(), 16);
Or if you think the presence of a space means there's something else wrong, you'll have to look into it yourself, since we don't have the rest of your code.
public static int hex2decimal(String s) {
String digits = "0123456789ABCDEF";
s = s.toUpperCase();
int val = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
int d = digits.indexOf(c);
val = 16*val + d;
}
return val;
}
That's the most efficient and elegant solution I have found on the Internet. Some of the other solutions provided here didn't always work for me.
//package com.javatutorialhq.tutorial;
import java.util.Scanner;
/* Java code to convert hexadecimal to decimal */
public class HexToDecimal {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.print("Hexadecimal Input: ");
// Read the hexadecimal input from the console
Scanner s = new Scanner(System.in);
String inputHex = s.nextLine();
try {
// Actual conversion of hexadecimal to decimal
Integer outputDecimal = Integer.parseInt(inputHex, 16);
System.out.println("Decimal Equivalent: " + outputDecimal);
}
catch(NumberFormatException ne) {
// Printing a warning message if the input
// is not a valid hexadecimal number
System.out.println("Invalid Input");
}
finally {
s.close();
}
}
}
My way:
private static int hexToDec(String hex) {
return Integer.parseInt(hex, 16);
}
This is my solution:
public static int hex2decimal(String s) {
int val = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
int num = (int) c;
val = 256*val + num;
}
return val;
}
For example to convert 3E8 to 1000:
StringBuffer sb = new StringBuffer();
sb.append((char) 0x03);
sb.append((char) 0xE8);
int n = hex2decimal(sb.toString());
System.out.println(n); //will print 1000.
You can use this method to get the digit:
public int digitToValue(char c) {
(c >= '&' && c <= '9') return c - '0';
else if (c >= 'A' && c <= 'F') return 10 + c - 'A';
else if (c >= 'a' && c <= 'f') return 10 + c - 'a';
return -1;
}
void htod(String hexadecimal)
{
int h = hexadecimal.length() - 1;
int d = 0;
int n = 0;
for(int i = 0; i<hexadecimal.length(); i++)
{
char ch = hexadecimal.charAt(i);
boolean flag = false;
switch(ch)
{
case '1': n = 1; break;
case '2': n = 2; break;
case '3': n = 3; break;
case '4': n = 4; break;
case '5': n = 5; break;
case '6': n = 6; break;
case '7': n = 7; break;
case '8': n = 8; break;
case '9': n = 9; break;
case 'A': n = 10; break;
case 'B': n = 11; break;
case 'C': n = 12; break;
case 'D': n = 13; break;
case 'E': n = 14; break;
case 'F': n = 15; break;
default : flag = true;
}
if(flag)
{
System.out.println("Wrong Entry");
break;
}
d = (int)(n*(Math.pow(16,h))) + (int)d;
h--;
}
System.out.println("The decimal form of hexadecimal number "+hexadecimal+" is " + d);
}
Since there is no brute-force approach which (done with it manualy). To know what exactly happened.
Given a hexadecimal number
KₙKₙ₋₁Kₙ₋₂....K₂K₁K₀
The equivalent decimal value is:
Kₙ * 16ₙ + Kₙ₋₁ * 16ₙ₋₁ + Kₙ₋₂ * 16ₙ₋₂ + .... + K₂ * 16₂ + K₁ * 16₁ + K₀ * 16₀
For example, the hex number AB8C is:
10 * 16₃ + 11 * 16₂ + 8 * 16₁ + 12 * 16₀ = 43916
Implementation:
//convert hex to decimal number
private static int hexToDecimal(String hex) {
int decimalValue = 0;
for (int i = 0; i < hex.length(); i++) {
char hexChar = hex.charAt(i);
decimalValue = decimalValue * 16 + hexCharToDecimal(hexChar);
}
return decimalValue;
}
private static int hexCharToDecimal(char character) {
if (character >= 'A' && character <= 'F')
return 10 + character - 'A';
else //character is '0', '1',....,'9'
return character - '0';
}
You could take advantage of ASCII value for each letter and take off 55, easy and fast:
int asciiOffset = 55;
char hex = Character.toUpperCase('A'); // Only A-F uppercase
int val = hex - asciiOffset;
System.out.println("hexadecimal:" + hex);
System.out.println("decimal:" + val);
Output:
hexadecimal:A
decimal:10
A much simpler way is to use BigInteger, like so:
BigInteger("625b", 16)
Scanner sc = new Scanner(System.in);
System.out.println("Enter the value");
String s = sc.next();
//String s = "AD";
String s1 = s.toUpperCase();
int power = 0;
double result = 0;
char[] c = s1.toCharArray();
for (int i = c.length-1; i >=0 ; i--) {
boolean a = true;
switch(c[i]){
case 'A': c[i] = 10; a = false; break;
case 'B': c[i] = 11; a = false; break;
case 'C': c[i] = 12; a = false; break;
case 'D': c[i] = 13; a = false; break;
case 'E': c[i] = 14; a = false; break;
case 'F': c[i] = 15; a = false; break;
}
if(a==true){
result = result + (c[i]-48) * Math.pow(16, power++);
}else {
result = result + (c[i]) * Math.pow(16, power++);
}
}
System.out.println(result);
This is a little library that should help you with hexadecimals in Java: https://github.com/PatrykSitko/HEX4J
It can convert from and to hexadecimals. It supports:
byte
boolean
char
char[]
String
short
int
long
float
double (signed and unsigned)
With it, you can convert your String to hexadecimal and the hexadecimal to a float/double.
Example:
String hexValue = HEX4J.Hexadecimal.from.String("Hello World");
double doubleValue = HEX4J.Hexadecimal.to.Double(hexValue);
Use:
public class Hex2Decimal {
public static void hexDec(String num)
{
int sum = 0;
int newnum = 0;
String digit = num.toUpperCase();
for(int i=0; i<digit.length(); i++)
{
char c = digit.charAt(digit.length()-i-1);
if(c == 'A')
{
newnum = 10;
}
else if(c == 'B')
{
newnum = 11;
}
if(c == 'C')
{
newnum = 12;
}
if(c == 'D')
{
newnum = 13;
}
if(c == 'E')
{
newnum = 14;
}
if(c == 'F')
{
newnum = 15;
}
else
{
newnum = Character.getNumericValue(c);
}
sum = (int) (sum + newnum*Math.pow(16, i));
}
System.out.println(" HexaDecimal to Decimal conversion is" + sum);
}
public static void main(String[] args) {
hexDec("9F");
}
}

Categories