Это - присвоение домашней работы, из-за которого я испытываю затруднения.
Я должен сделать целое число к преобразователю Римской цифры с помощью метода. Позже, я должен затем использовать программу для выписывания 1 - 3 999 в Римских цифрах, таким образом, жесткое кодирование отсутствует. Мой код ниже является очень базовым; это - основной цикл ввода-вывода со способом выйти при использовании пакета для getIntegerFromUser
мы сделали в классе.
Существует ли способ присвоить значения Строкам и затем добавить их вместе, когда я называю метод?
Обновление: Я заставил некоторый псевдо код от своего преподавателя помогать мне, и в то время как я понимаю то, что он пытается сказать, я испытываю некоторые затруднения из-за if
s. Мне будут нужны многие, многие 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;
}
Сначала повредитесь, число в его десятичные факторы как 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
Мне нравится использовать Цепочка шаблона 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Только, чтобы не отставать от технологии, вот версия 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); }
}
}