Хорошим местом для начала является JavaDocs . Они охватывают это:
Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
- Вызов метода экземпляра нулевого объекта.
- Доступ или изменение поля нулевого объекта.
- Выполнение длины null, как если бы это был массив.
- Доступ или изменение слотов с нулевым значением, как если бы это был массив.
- Бросать нуль, как если бы это было значение Throwable.
Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.
blockquote>Также, если вы попытаетесь использовать нулевую ссылку с
synchronized
, который также выдаст это исключение, за JLS :SynchronizedStatement: synchronized ( Expression ) Block
blockquote>
- В противном случае, если значение выражения равно null,
NullPointerException
.Как это исправить?
Итак, у вас есть
NullPointerException
. Как вы это исправите? Возьмем простой пример, который выдаетNullPointerException
:public class Printer { private String name; public void setName(String name) { this.name = name; } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer(); printer.print(); } }
Идентифицирует нулевые значения
. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:
Exception in thread "main" java.lang.NullPointerException at Printer.printString(Printer.java:13) at Printer.print(Printer.java:9) at Printer.main(Printer.java:19)
Здесь мы видим, что исключение выбрано в строке 13 (в методе
printString
). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, чтоs
имеет значение null, а вызов методаlength
на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когдаs.length()
удаляется из метода.Трассировка, где эти значения взяты из
Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что
s
передается сprintString(name)
в методеprint()
, аthis.name
- null.Трассировка, где эти значения должны быть установлены
Где установлен
this.name
? В методеsetName(String)
. С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. Этого достаточно, чтобы дать нам решение: добавить вызов
printer.setName()
перед вызовомprinter.print()
.Другие исправления
Переменная может иметь значение по умолчанию (и
setName
может помешать ему установить значение null):private String name = "";
Либо метод
printString
может проверить значение null например:printString((name == null) ? "" : name);
Или вы можете создать класс, чтобы
name
всегда имел ненулевое значение :public class Printer { private final String name; public Printer(String name) { this.name = Objects.requireNonNull(name); } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer("123"); printer.print(); } }
См. также:
Я все еще не могу найти проблему
Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).
Я играл вокруг с синтаксическим анализатором ШТЕПСЕЛЯ, чтобы сделать то, что Вы хотели (и может отправить это как отдельный ответ позже), когда я заметил, что существует очень простой алгоритм, который делает удивительно хорошее задание со стандартными формами чисел на английском, испанском и немецком языке, по крайней мере.
Работа с английским языком, например, Вам нужен словарь, который отображает слова на значения очевидным способом:
"one" -> 1, "two" -> 2, ... "twenty" -> 20,
"dozen" -> 12, "score" -> 20, ...
"hundred" -> 100, "thousand" -> 1000, "million" -> 1000000
... и т.д
алгоритм справедлив:
total = 0
prior = null
for each word w
v <- value(w) or next if no value defined
prior <- case
when prior is null: v
when prior > v: prior+v
else prior*v
else
if w in {thousand,million,billion,trillion...}
total <- total + prior
prior <- null
total = total + prior unless prior is null
, Например, это прогрессирует следующим образом:
total prior v unconsumed string
0 _ four score and seven
4 score and seven
0 4
20 and seven
0 80
_ seven
0 80
7
0 87
87
total prior v unconsumed string
0 _ two million four hundred twelve thousand eight hundred seven
2 million four hundred twelve thousand eight hundred seven
0 2
1000000 four hundred twelve thousand eight hundred seven
2000000 _
4 hundred twelve thousand eight hundred seven
2000000 4
100 twelve thousand eight hundred seven
2000000 400
12 thousand eight hundred seven
2000000 412
1000 eight hundred seven
2000000 412000
1000 eight hundred seven
2412000 _
8 hundred seven
2412000 8
100 seven
2412000 800
7
2412000 807
2412807
И так далее. Я не говорю, что это идеально подходит, но для быстрого и грязного, это вполне успевает.
<час>Обращение к Вашему определенному списку на редактировании:
, Номер 6 является единственным, у меня нет готового ответа для, и поэтому неоднозначности между ординалами и частями (на английском языке, по крайней мере) добавленным к тому, что моя последняя чашка кофе была многие несколько часов назад.
Попробуйте
, Открывают Запрос HTTP для" http://www.google.com/search?q= " + число + "+in+decimal".
Синтаксический анализ результат для Вашего числа.
Кэшируют число / пары результата к уроку запросы со временем.
Одно место, чтобы начать смотреть гну get_date lib , который может проанализировать примерно любой английская текстовая дата в метку времени. В то время как не точно, что Вы ищете, их решение подобной проблемы могло дать много полезных представлений.
Моя реализация LPC некоторых Ваших требований (только американский вариант английского языка):
internal mapping inordinal = ([]);
internal mapping number = ([]);
#define Numbers ([\
"zero" : 0, \
"one" : 1, \
"two" : 2, \
"three" : 3, \
"four" : 4, \
"five" : 5, \
"six" : 6, \
"seven" : 7, \
"eight" : 8, \
"nine" : 9, \
"ten" : 10, \
"eleven" : 11, \
"twelve" : 12, \
"thirteen" : 13, \
"fourteen" : 14, \
"fifteen" : 15, \
"sixteen" : 16, \
"seventeen" : 17, \
"eighteen" : 18, \
"nineteen" : 19, \
"twenty" : 20, \
"thirty" : 30, \
"forty" : 40, \
"fifty" : 50, \
"sixty" : 60, \
"seventy" : 70, \
"eighty" : 80, \
"ninety" : 90, \
"hundred" : 100, \
"thousand" : 1000, \
"million" : 1000000, \
"billion" : 1000000000, \
])
#define Ordinals ([\
"zeroth" : 0, \
"first" : 1, \
"second" : 2, \
"third" : 3, \
"fourth" : 4, \
"fifth" : 5, \
"sixth" : 6, \
"seventh" : 7, \
"eighth" : 8, \
"ninth" : 9, \
"tenth" : 10, \
"eleventh" : 11, \
"twelfth" : 12, \
"thirteenth" : 13, \
"fourteenth" : 14, \
"fifteenth" : 15, \
"sixteenth" : 16, \
"seventeenth" : 17, \
"eighteenth" : 18, \
"nineteenth" : 19, \
"twentieth" : 20, \
"thirtieth" : 30, \
"fortieth" : 40, \
"fiftieth" : 50, \
"sixtieth" : 60, \
"seventieth" : 70, \
"eightieth" : 80, \
"ninetieth" : 90, \
"hundredth" : 100, \
"thousandth" : 1000, \
"millionth" : 1000000, \
"billionth" : 1000000000, \
])
varargs int denumerical(string num, status ordinal) {
if(ordinal) {
if(member(inordinal, num))
return inordinal[num];
} else {
if(member(number, num))
return number[num];
}
int sign = 1;
int total = 0;
int sub = 0;
int value;
string array parts = regexplode(num, " |-");
if(sizeof(parts) >= 2 && parts[0] == "" && parts[1] == "-")
sign = -1;
for(int ix = 0, int iix = sizeof(parts); ix < iix; ix++) {
string part = parts[ix];
switch(part) {
case "negative" :
case "minus" :
sign = -1;
continue;
case "" :
continue;
}
if(ordinal && ix == iix - 1) {
if(part[0] >= '0' && part[0] <= '9' && ends_with(part, "th"))
value = to_int(part[..<3]);
else if(member(Ordinals, part))
value = Ordinals[part];
else
continue;
} else {
if(part[0] >= '0' && part[0] <= '9')
value = to_int(part);
else if(member(Numbers, part))
value = Numbers[part];
else
continue;
}
if(value < 0) {
sign = -1;
value = - value;
}
if(value < 10) {
if(sub >= 1000) {
total += sub;
sub = value;
} else {
sub += value;
}
} else if(value < 100) {
if(sub < 10) {
sub = 100 * sub + value;
} else if(sub >= 1000) {
total += sub;
sub = value;
} else {
sub *= value;
}
} else if(value < sub) {
total += sub;
sub = value;
} else if(sub == 0) {
sub = value;
} else {
sub *= value;
}
}
total += sub;
return sign * total;
}
Ну, я слишком опаздывал на ответе для этого вопроса, но я работал немного сценария тестирования, который, кажется, работал очень хорошо на меня. Я использовал (простой, но ужасный, и большой) регулярное выражение для определения местоположения всех слов для меня. Выражение следующие:
(?<Value>(?:zero)|(?:one|first)|(?:two|second)|(?:three|third)|(?:four|fourth)|
(?:five|fifth)|(?:six|sixth)|(?:seven|seventh)|(?:eight|eighth)|(?:nine|ninth)|
(?:ten|tenth)|(?:eleven|eleventh)|(?:twelve|twelfth)|(?:thirteen|thirteenth)|
(?:fourteen|fourteenth)|(?:fifteen|fifteenth)|(?:sixteen|sixteenth)|
(?:seventeen|seventeenth)|(?:eighteen|eighteenth)|(?:nineteen|nineteenth)|
(?:twenty|twentieth)|(?:thirty|thirtieth)|(?:forty|fortieth)|(?:fifty|fiftieth)|
(?:sixty|sixtieth)|(?:seventy|seventieth)|(?:eighty|eightieth)|(?:ninety|ninetieth)|
(?<Magnitude>(?:hundred|hundredth)|(?:thousand|thousandth)|(?:million|millionth)|
(?:billion|billionth)))
Показанный здесь с разрывами строки для форматирования целей..
Так или иначе, мой метод должен был выполнить этот RegEx с библиотекой как PCRE и затем считать назад именованные соответствия. И это работало надо всеми различными примерами, перечисленными в этом вопросе, минус "Одна Половина", типы, поскольку я не включал их, но как Вы видите, не было бы трудно сделать так. Это решает много проблем. Например, это обращается к следующим объектам в исходном вопросе и других ответах:
Теперь, вместо того, чтобы сохранить этого монстра регулярного выражения в Вашем источнике, я рассматривал создание этого RegEx во времени выполнения, с помощью чего-то как следующее:
char *ones[] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve",
"thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
char *tens[] = {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
char *ordinalones[] = { "", "first", "second", "third", "fourth", "fifth", "", "", "", "", "", "", "twelfth" };
char *ordinaltens[] = { "", "", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth", "seventieth", "eightieth", "ninetieth" };
and so on...
легкая часть здесь, мы только храним слова тот вопрос. В случае ШЕСТОГО Вы заметите, что нет записи для него, потому что это просто, это - нормальное число с TH, прикрепляемым на... Но как ДВЕНАДЦАТЬ потребностей другое внимание.
хорошо, поэтому теперь у нас есть код для создания нашего (ужасного) RegEx, теперь мы просто выполняем его на наших числовых строках.
Одна вещь, которую я рекомендовал бы, состоит в том, чтобы отфильтровать или съесть слово "И". Это не необходимо, и только приводит к другим проблемам.
Так, то, что Вы собираетесь хотеть сделать, установить функцию, которая передает именованные соответствия для "Величины" в функцию, которая смотрит на все возможные значения величины и умножает Ваш текущий результат на то значение величины. Затем Вы создаете функцию, которая смотрит на "Значение", названное соответствиями, и возвращает интервал (или независимо от того, что Вы используете), на основе значения, обнаруженного там.
Все соответствия ЗНАЧЕНИЯ ДОБАВЛЯЮТСЯ к Вашему результату, в то время как соответствия magnitutde умножают результат на значение mag. Так, Двести пятьдесят тысяч становится "2", тогда "2 * 100", тогда "200 + 50", тогда "250 * 1000", заканчиваясь с 250 000...
Только для забавы, я записал vbScript версию этого, и она работала отлично со всеми обеспеченными примерами. Теперь, это не поддерживает названные соответствия, таким образом, я должен был работать немного более трудное получение корректного результата, но я получил его. Нижняя строка, если это - соответствие "ЗНАЧЕНИЯ", добавьте его Ваш аккумулятор. Если это - соответствие величины, умножьте свой аккумулятор на 100, 1000, 1000000, 1000000000, и т.д... Это предоставит Вам некоторые довольно удивительные результаты и все, что необходимо сделать для корректировки для вещей как "одна половина", добавляют их к RegEx, вставляют маркер кода для них и обрабатывают их.
ну, я надеюсь, что это сообщение помогает КОМУ-ТО там. Если кто-либо хочет, я могу отправить vbScript псевдо кодом, что я раньше тестировал это с, однако, это не симпатичный код и НЕ производственный код.
, Если я могу.. Каков заключительный язык, в котором это будет записано? C++ или что-то как язык в виде сценария? Источник Greg Hewgill будет иметь большое значение в помощи, понимают, как все это объединяется.
Сообщенный мне, если я могу иметь какую-либо другую справку. Извините, я только знаю английский язык/Американца, таким образом, я не могу помочь Вам с другими языками.
Необходимо иметь в виду, что Европа и Америка рассчитывают по-другому.
One Thousand
One Million
One Thousand Millions (British also use Milliard)
One Billion
One Thousand Billions
One Trillion
One Thousand Trillions
Здесь маленькая ссылка на нем.
<час>А простой способ видеть различие следующий:
(American counting Trillion) == (European counting Billion)
У меня есть некоторый код, который я записал только что: text2num. Это делает часть из того, что Вы хотите, кроме него не обрабатывает порядковые числа. Я на самом деле не использовал этот код ни для чего, таким образом, он в основном не тестируется!
Это не легкая проблема, и я не знаю ни о какой библиотеке, чтобы сделать это. Я мог бы сесть и попытаться записать что-то вроде этого когда-то. Я сделал бы это или в Прологе, Java или в Haskell, все же. Насколько я вижу, существует несколько проблем:
, Если Вы интересуетесь этим, я мог бы дать ему выстрел в эти выходные. Моя идея, вероятно, использует UIMA и маркирует с ним, затем продолжая далее маркировать/снимать неоднозначность и наконец переводить. Могло бы быть больше проблем, давайте посмотрим, могу ли я придумать некоторые более интересные вещи.
Извините, это еще не реальный ответ, просто расширение Вашего вопроса. Я сообщу, нахожу ли я/пишу что-то.
Между прочим, если Вы интересуетесь семантикой цифр, я просто нашел интересная бумага Friederike Moltmann, обсудив некоторые вопросы относительно логической интерпретации цифр.
Порядковые числа не применимы, потому что они наклоняются быть присоединенными значимыми способами с другими числами на языке (..., по крайней мере, на английском языке)
, например, сто первые, одиннадцатисекундные, и т.д.
Однако существует другой английский/Американский протест со словом 'и'
т.е.
сто один (английский) сто один (американец)
кроме того, использование для значения один на английском языке
тысяча = одна тысяча
... На стороне отмечают, что калькулятор Google делает удивительное задание этого.
сто три тысячи раз скорость света
И даже...
... wtf?!? счет плюс дюжина в римских цифрах