Преобразование целых чисел к римским цифрам - Java

Это - присвоение домашней работы, из-за которого я испытываю затруднения.

Я должен сделать целое число к преобразователю Римской цифры с помощью метода. Позже, я должен затем использовать программу для выписывания 1 - 3 999 в Римских цифрах, таким образом, жесткое кодирование отсутствует. Мой код ниже является очень базовым; это - основной цикл ввода-вывода со способом выйти при использовании пакета для getIntegerFromUser мы сделали в классе.

Существует ли способ присвоить значения Строкам и затем добавить их вместе, когда я называю метод?

Обновление: Я заставил некоторый псевдо код от своего преподавателя помогать мне, и в то время как я понимаю то, что он пытается сказать, я испытываю некоторые затруднения из-за ifs. Мне будут нужны многие, многие if операторы так, чтобы мой преобразователь правильно обработал форматирование Римской цифры или был там способом, в который я могу сделать это с большей эффективностью? Я обновил свой код для отражения моего метода заполнителя.

Обновление (28 октября 2012): Я получил его работа. Вот то, что я закончил тем, что использовал:

public static String IntegerToRomanNumeral(int input) {
    if (input < 1 || input > 3999)
        return "Invalid Roman Number Value";
    String s = "";
    while (input >= 1000) {
        s += "M";
        input -= 1000;        }
    while (input >= 900) {
        s += "CM";
        input -= 900;
    }
    while (input >= 500) {
        s += "D";
        input -= 500;
    }
    while (input >= 400) {
        s += "CD";
        input -= 400;
    }
    while (input >= 100) {
        s += "C";
        input -= 100;
    }
    while (input >= 90) {
        s += "XC";
        input -= 90;
    }
    while (input >= 50) {
        s += "L";
        input -= 50;
    }
    while (input >= 40) {
        s += "XL";
        input -= 40;
    }
    while (input >= 10) {
        s += "X";
        input -= 10;
    }
    while (input >= 9) {
        s += "IX";
        input -= 9;
    }
    while (input >= 5) {
        s += "V";
        input -= 5;
    }
    while (input >= 4) {
        s += "IV";
        input -= 4;
    }
    while (input >= 1) {
        s += "I";
        input -= 1;
    }    
    return s;
}
60
задан 11 September 2015 в 00:33

3 ответа

Сначала повредитесь, число в его десятичные факторы как 995 = 900 + 90 + 5 затем преобразовывают каждый фактор рекурсивно

public class IntegerToRoman {
  private Map<Integer, String> romanChars = new HashMap<>();

  public IntegerToRoman() {
    romanChars.put(1, "I");
    romanChars.put(5, "V");
    romanChars.put(10, "X");
    romanChars.put(50, "L");
    romanChars.put(100, "C");
    romanChars.put(500, "D");
    romanChars.put(1000, "M");
    romanChars.put(5000, "V|");
 }

 public String intToRoman(int num) {
    if (num == 0) {
        return "";
    }
    int decimalFact = 0;
    StringBuilder result = new StringBuilder();
    for (int i = (int)Math.log10(num); i >= 0; i--) {
        int divisor = (int) Math.pow(10, i);
        decimalFact = num - num % divisor;
        result.append(convertDecimalFact(decimalFact));
        num = num % divisor;
    }
    return result.toString();
}

private String convertDecimalFact(int decimalFact){
  if(decimalFact == 0){return "";}
  int[] keyArray = romanChars.keySet().stream().mapToInt(key -> key) 
       .sorted().toArray(); 

  for(int i =0 ; i+1<keyArray.length ; i++){
      if( keyArray[i] <= decimalFact && decimalFact<= keyArray[i+1]  ){
         int bigger1stDgt = getLeftMostNum(keyArray[i+1]);
         int decimalFact1stDgt = getLeftMostNum(decimalFact);
         return decimalFact1stDgt >= bigger1stDgt-1 ? 
                intToRoman(keyArray[i+1]-decimalFact)+romanChars.get(keyArray[i+1]): 
                romanChars.get(keyArray[i])+intToRoman(decimalFact - keyArray[i]);
      }
  }      
  return "";
}

private int getLeftMostNum(int number) {
    int oneDgt = Integer.valueOf(Integer.valueOf(number).toString()
                 .substring(0, 0 +1));
    if(number<10){
        return oneDgt;
    }       
    int twoDgts = Integer.valueOf(Integer.valueOf(number).toString()
                  .substring(0, 0 +2));
    return twoDgts==10 ? twoDgts : oneDgt;
}

public static void main(String[] args) {

    IntegerToRoman solution = new IntegerToRoman();
    System.out.format(" Decimal 3 -> Roman %s \n ", solution.intToRoman(3));
    System.out.format("Decimal 4 -> Roman %s \n ", solution.intToRoman(4));
    System.out.format("Decimal 8 -> Roman %s \n ", solution.intToRoman(8));
    System.out.format("Decimal 58 -> Roman %s \n ", solution.intToRoman(58));
    System.out.format("Decimal 344 -> Roman %s \n ", solution.intToRoman(344));
    System.out.format("Decimal 995 -> Roman %s \n ", solution.intToRoman(995));
    System.out.format("Decimal 1994 -> Roman %s \n ", solution.intToRoman(1994));
}

}

, Вывод похож:

Десятичные 3-> Roman III

Десятичные 4-> римское Десятичное число IV

8-> Roman VIII

Десятичные 58-> Roman LVIII

Десятичные 344-> Roman CCCXLIV

Десятичные 995-> Roman CMXCV

Десятичный 1994-> Roman MCMXCIV

0
ответ дан 31 October 2019 в 16:39

Мне нравится использовать Цепочка шаблона Responsiblity самому. Я думаю, что это имеет большой смысл для этого сценария.

public abstract class NumberChainOfResponsibility {
    protected NumberChainOfResponsibility next;
    protected int decimalValue;
    protected String romanNumeralValue;

    public NumberChainOfResponsibility() {
    }

    public String convert(int decimal) {
        int remainder = decimal;
        StringBuilder numerals = new StringBuilder();
        while (remainder != 0) {
            if (remainder >= this.decimalValue) {
                numerals.append(this.romanNumeralValue);
                remainder -= this.decimalValue;
            } else {
                numerals.append(next.convert(remainder));
                remainder = 0;
            }
        }
        return numerals.toString();
    }
}

Затем я создаю класс, расширяющий этого для каждой римской цифры (1/5/10/50/100/500/1000, а также 4/9/40/90/400/900).

1000

public class Cor1000 extends NumberChainOfResponsibility {
    public Cor1000() {
        super();
        this.decimalValue = 1000;
        this.romanNumeralValue = "M";
        this.next = new Cor900();
    }
}

1

public class Cor1 extends NumberChainOfResponsibility {
    public Cor1() {
        super();
        this.decimalValue = 1;
        this.romanNumeralValue = "I";
        this.next = null;
    }
}

класс А, служащий "интерфейсом" к преобразователю, выставляя метод для преобразования определенного числа.

public class Converter {
    private static int MAX_VALUE = 5000;
    private static int MIN_VALUE = 0;
    private static String ERROR_TOO_BIG = "Value is too big!";
    private static String ERROR_TOO_SMALL = "Value is too small!";

    public String convertThisIntToRomanNumerals(int decimal) {
        Cor1000 startingCor = new Cor1000();
        if (decimal >= MAX_VALUE)
            return ERROR_TOO_BIG;
        if (decimal <= MIN_VALUE)
            return ERROR_TOO_SMALL;

        String numeralsWithoutConversion = startingCor.convert(decimal);
        return numeralsWithoutConversion;
    }
}

И клиентский код (в моем случае тест JUnit).

@Test
public void assertConversionWorks() {
    Assert.assertEquals("MMMMCMXCIX", converter.convertThisIntToRomanNumerals(4999));
    Assert.assertEquals("CMXCIX", converter.convertThisIntToRomanNumerals(999));
    Assert.assertEquals("CMLXXXIX", converter.convertThisIntToRomanNumerals(989));
    Assert.assertEquals("DCXXVI", converter.convertThisIntToRomanNumerals(626));
    Assert.assertEquals("DCXXIV", converter.convertThisIntToRomanNumerals(624));
    Assert.assertEquals("CDXCVIII", converter.convertThisIntToRomanNumerals(498));
    Assert.assertEquals("CXXIII", converter.convertThisIntToRomanNumerals(123));
    Assert.assertEquals("XCIX", converter.convertThisIntToRomanNumerals(99));
    Assert.assertEquals("LI", converter.convertThisIntToRomanNumerals(51));
    Assert.assertEquals("XLIX", converter.convertThisIntToRomanNumerals(49));
}

Посмотрите целый пример на моем учетная запись .

GitHub
0
ответ дан 31 October 2019 в 16:39

Только, чтобы не отставать от технологии, вот версия Java 8 с помощью потоков и пользовательского Коллектора, избавляя от необходимости циклы или если операторы:

import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.IntStream;

public class RomanNumeral {

    public static void main(String arg[]) {
        IntStream.range(1, 4000).forEach(value -> System.out.println( Arrays.stream(Mark.values()).collect(new MarkCollector<Mark>(value)).toString()));
    }

    enum Mark {
        M(1000), CM(900), D(500), CD(400), C(100), XC(90), L(50), XL(40), X(10), IX(9), V(5), IV(4), I(1);

        private final int value;

        private Mark(int value) { this.value = value; }

        public int value() { return value; }
    }

    static class MarkCollector<T extends Mark> implements Collector<T, StringBuilder, StringBuilder> {

        private final int[] valueholder = new int[1];

        MarkCollector(int value) { valueholder[0] = value; }

        @Override
        public Supplier<StringBuilder> supplier() { return () -> StringBuilder::new; }

        @Override
        public BiConsumer<StringBuilder, T> accumulator() {
            return (builder, mark) -> {
                builder.append(String.join("", Collections.nCopies(valueholder[0] / mark.value(), mark.name())));
                valueholder[0] = valueholder[0] % mark.value();
            };
        }

        @Override
        public BinaryOperator<StringBuilder> combiner() { return null; }

        @Override
        public Function<StringBuilder, StringBuilder> finisher() { return Function.identity(); }

        @Override
        public Set<Characteristics> characteristics() { return Collections.singleton(Characteristics.IDENTITY_FINISH); }
    }
}
0
ответ дан 31 October 2019 в 16:39

Другие вопросы по тегам:

Похожие вопросы: