1

大家好,我正在完成一个在线练习,我必须创建一个程序来读取几段文本。所有数字(以文本形式编写)必须相加,并在末尾显示总和。

如果你们不介意回答,我有几个问题,因为我对此进行了相当多的研究。

这只是使用的文本示例:

例如,请记住,您正站在十二点钟的站台上,有五辆火车在九个轨道上每小时运行一次。一列火车的速度可以达到每小时两百英里。亿万中的一...

我正在使用 StringTokenizer,因此每个单词都是单独读取的。

通过研究,我学会了创建表示每个单词的数组(请参见代码示例),这样单词就可以很容易地表示为整数。虽然我也为每个数字创建了变量,但这可能不是必需的,尽管我不明白 Java 如何将一个单词表示为它的有效数字。(再次请参阅代码)。

虽然我最大的问题是我将如何使用循环组合像 281 = 281 这样的单词。

任何建议将不胜感激,我知道这段代码远非完美,因为我正在继续通过在线材料和书籍学习。

class wordsToNumberAdder

{
    public static void main()
{   

    String str = "Just remember that you're standing on a platform at twelve o'clock and there are 
    five trains that run every hour on nine tracks. A train can go as fast as two hundred miles
    an hour. One of millions of billions... ";

    StringTokenizer st = new StringTokenizer(str);


String[] digits = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
String[] tens = {"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
String[] teens = {"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
String[] power = {"hundred","thousand","million","billion"};

int one = 1, two = 2, three = 3, four = 4, five = 5, six = 6, seven = 7, eight = 8, nine = 9;
int twenty = 20, thirty = 30, forty = 40, fifty = 50, sixty = 60, seventy = 70, eighty = 80, ninety = 90;
int ten = 10, eleven = 11, twelve = 12, thirteen = 13, forteen = 14, fifthteen = 15, sixteen = 16;
int eighteen = 18, nineteen = 19, thirty = 30, hundred = 100, thousand = 1000; 
long billion = 1000000000;

double result = 0;
double group = 0;

while (set.hasMoreTokens()) {
        String word = set.nextToken();

for (int x = 0; x < power.length; i += 3) {

            if (word.equals(power[i])) {
            group = group * Math.pow(10, i);
            result = result + group;
            group = 0;
        }
    }
4

1 回答 1

2

对我来说,这里有两个子问题:将输入解析为数字短语的集合(“204”等)并将这些数字短语转换为实际值以求和。

没有理由不使用映射来解析单词的值。因此,请尝试以下方法,而不是所有这些字段:

private static final Map<String, Long> NUMBER_MAP;
static {
  final Map<String, Long> map = new HashMap<String, Long>();
  map.put("one", 1L);
  map.put("two", 2L);
  map.put("three", 3L);
  ...
  map.put("hundred", 100L);
  map.put("hundreds", 100L);
  ...
  map.put("billion", 1000000000L);
  map.put("billions", 1000000000L);
  NUMBER_MAP = Collections.unmodifiableMap(map);
}

关于这一点的几件事:首先,它是不可变的,因此这些映射都不能改变,最好的做法是尽量减少代码中的可变性。我还添加了几个单词的复数以简化解析。可能有一种更优雅的方式来处理这些复数,但我保持简单。我也有一切,只要简单。

现在,用于解析。使用 StringTokenizer 是一个好的开始,但您并没有做太多事情。以下是我将如何实现解析:

public static void main(final String[] args) {
  final StringTokenizer tokenizer = new StringTokenizer(paragraph.replace(".", " ").toLowerCase());
  final StringBuilder phrase = new StringBuilder();
  final Set<String> numberSet = NUMBER_MAP.keySet();

  while (tokenizer.hasMoreTokens()) {
    final String token = tokenizer.nextToken();

    if (numberSet.contains(token)) {
      if (phrase.length() > 0) {
        phrase.append(" ");
      }
      phrase.append(token);
    } else if (!IGNORED_WORDS.contains(token)) {
      processPhrase(phrase.toString());
      phrase.setLength(0);
    }
  }

  processPhrase(phrase.toString());
}

那么我在这里做了什么?首先,我正在清理输入字符串以处理句点和大写字母。这样我们就可以解析像“一百”这样的句子。然后我使用 StringBuilder 来有效地构建数字短语。如果下一个标记(单词)在我们数字的键集中(例如“十八”或“一百”),我将它添加到当前短语中,如果它不是短语中的第一个单词,则在前面加上一个空格。IGNORED_WORDS 是一个(不可变的)集合,只包含字符串“and”。例如,这让我们可以解析“一百一十”。

那么短语到数字的转换呢?你上面写的循环对我来说没有多大意义。是什么i?是什么x?这是什么错字?我使用的一般方法是一次考虑两个词。如果只有一个,那很容易,我们就完成了。但是,如果有两个,我们必须考虑它们的顺序。以“九百”为例。因为第二个值 (100) 大于第一个 (9),所以我们将它们相乘并将它们加到总和中。如果之前的计算值大于当前值,我们只需将它们相加。这样,解析“12200”看起来像:

12 < 1000 : current sum = 12 * 1000 = 12000
2 < 100 : current sum += 2 * 100 = 12000 + 200 = 12200

我没有对其进行过多测试,但您可以在此处查看我的实现

附录

地图在任何编程语言中都非常酷。映射是一对一(双射)函数:Java 映射中的键是函数的域,键映射到的值是范围。您可以使用 提取所有键的集合,使用(其中是实例化的 Map 变量)提取map.keySet()值。更强大的功能如下:map.values()map

for (Map.Entry<K, V> entry : map.entrySet()) { 
  // loop over all entries in the map 
}

这实际上是对映射中每个映射的迭代器,您可以在每次迭代时获取键和值。

无论如何,如果我们有一个 map 变量,并且 go map.keySet(),我们会得到一个包含该 map 中所有键的 Java Set。在这篇文章的实例中,这个 Set 将包括字符串“one”、“two”、...“billions”。换句话说,如果我有一组语句“A 映射到 B”,并要求 keySet,我会得到这些语句中的所有 'A'。

因此,将 NUMBER_MAP 视为从英文数字(键)到数学数字(值)的映射。从段落中的英文数字开始,我想得到数学数字。为此,我将段落中的值与地图中的键进行了比较。

于 2013-06-29T16:38:34.673 回答