Если вы хотите вычислить максимум двух чисел, стандартный подход в сборке ARM выглядит примерно так:
cmp r0, r1 @ if r0 > r1
movgt r2, r0 @ then r2 = r0
movle r2, r1 @ else r2 = r1
Чтобы добавить максимум r0
, r1
и [114 ] до r3
вы можете захотеть что-то вроде этого:
cmp r0, r1 @ if r0 < r1
movlt r0, r1 @ then r0 = r1 (i.e. r0 = max(r0, r1))
cmp r0, r2 @ if r0 < r2
movlt r0, r2 @ then r0 = r2 (i.e. r0 = max(max(r0, r1), r2))
add r3, r0, r3 @ r3 += r0
реализовать это так, чтобы вы не загромождали какие-либо регистры, оставляя читателю в качестве упражнения.
Всегда имейте в виду, что почти каждая инструкция может быть выполнена условно на ARM. В этом вся сила набора инструкций.
Я не полагаю, что существует что-либо встроенное в Java, чтобы сделать это быстрее и все еще надежно, предполагая, что позже Вы захотите на самом деле проанализировать его с Double.valueOf (или подобный).
Я использовал бы Double.parseDouble вместо Double.valueOf, чтобы не создавать Двойное излишне, и можно также избавиться от очевидно глупых чисел, более быстрых, чем исключение будет путем проверки на цифры, e/E, - и. заранее. Так, что-то как:
public boolean isDouble(String value)
{
boolean seenDot = false;
boolean seenExp = false;
boolean justSeenExp = false;
boolean seenDigit = false;
for (int i=0; i < value.length(); i++)
{
char c = value.charAt(i);
if (c >= '0' && c <= '9')
{
seenDigit = true;
continue;
}
if ((c == '-' || c=='+') && (i == 0 || justSeenExp))
{
continue;
}
if (c == '.' && !seenDot)
{
seenDot = true;
continue;
}
justSeenExp = false;
if ((c == 'e' || c == 'E') && !seenExp)
{
seenExp = true;
justSeenExp = true;
continue;
}
return false;
}
if (!seenDigit)
{
return false;
}
try
{
Double.parseDouble(value);
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
Обратите внимание, что несмотря на взятие нескольких попыток, это все еще не покрывает "NaN" или преобразовывает значения в шестнадцатеричную систему. Хотите ли Вы, чтобы они передали, или не зависит от контекста.
По моему опыту, регулярные выражения медленнее, чем трудно кодированная проверка выше.
Вы могли использовать regex, т.е. что-то как String.matches("^[\\d\\-\\.]+$");
(если Вы не тестируете на отрицательные числа или числа с плавающей точкой, Вы могли бы упростить немного).
Не уверенный, было ли это быстрее, чем метод, который Вы обрисовали в общих чертах все же.
Править: в свете всего этого противоречия я решил сделать тест и получить некоторые данные о том, как быстро каждый из этих методов был. Не так правильность, но как быстро они работали.
Можно читать о моих результатах на моем блоге. (Подсказка: Jon Skeet FTW).
Корректный regex на самом деле подан Двойной javadocs:
Чтобы постараться не называть этот метод на недопустимой строке и иметь NumberFormatException быть брошенным, регулярное выражение ниже может использоваться для экранирования входной строки:
final String Digits = "(\\p{Digit}+)";
final String HexDigits = "(\\p{XDigit}+)";
// an exponent is 'e' or 'E' followed by an optionally
// signed decimal integer.
final String Exp = "[eE][+-]?"+Digits;
final String fpRegex =
("[\\x00-\\x20]*"+ // Optional leading "whitespace"
"[+-]?(" + // Optional sign character
"NaN|" + // "NaN" string
"Infinity|" + // "Infinity" string
// A decimal floating-point string representing a finite positive
// number without a leading sign has at most five basic pieces:
// Digits . Digits ExponentPart FloatTypeSuffix
//
// Since this method allows integer-only strings as input
// in addition to strings of floating-point literals, the
// two sub-patterns below are simplifications of the grammar
// productions from the Java Language Specification, 2nd
// edition, section 3.10.2.
// Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
"((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
// . Digits ExponentPart_opt FloatTypeSuffix_opt
"(\\.("+Digits+")("+Exp+")?)|"+
// Hexadecimal strings
"((" +
// 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "(\\.)?)|" +
// 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
")[pP][+-]?" + Digits + "))" +
"[fFdD]?))" +
"[\\x00-\\x20]*");// Optional trailing "whitespace"
if (Pattern.matches(fpRegex, myString))
Double.valueOf(myString); // Will not throw NumberFormatException
else {
// Perform suitable alternative action
}
Это не допускает локализованные представления, однако:
Для интерпретации представлений локализованной строки значения с плавающей точкой используйте подклассы NumberFormat.
См. java.text. NumberFormat (javadoc).
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
Number myNumber = nf.parse(myString);
int myInt = myNumber.intValue();
double myDouble = myNumber.doubleValue();
Использовать StringUtils.isDouble(String)
в Apache палата общин.
Я использовал бы Джакарту Ленг свободного городского населения, как всегда! Но я понятия не имею, быстра ли их реализация или нет. Это не полагается на Исключения, которые могли бы быть хорошей мудрой производительностью бедра...
Большинство этих ответов является несколько приемлемыми решениями. Все regex решения имеют проблему того, чтобы не быть корректным для всех случаев, о которых можно заботиться.
Если Вы действительно хотите удостовериться, что Строка является верным номером, то я использовал бы Ваше собственное решение. Не забывайте, что, я воображаю, что большую часть времени Строка будет верным номером и не повысит исключение. Таким образом, большую часть времени производительность будет идентична производительности Double.valueOf ().
Я предполагаю, что это действительно не ответ, за исключением того, что он проверяет Ваш начальный инстинкт.
Randy
Усиление от г-на Skeet:
private boolean IsValidDoubleChar(char c)
{
return "0123456789.+-eE".indexOf(c) >= 0;
}
public boolean isDouble(String value)
{
for (int i=0; i < value.length(); i++)
{
char c = value.charAt(i);
if (IsValidDoubleChar(c))
continue;
return false;
}
try
{
Double.parseDouble(value);
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
Ответ следующего Phill я могу предложить другой regex?
String.matches("^-?\\d+(\\.\\d+)?$");
Я предпочитаю использовать цикл по символу Строк [] представление и использовать Character.isDigit () метод. Если элегантность желаема, я думаю, что это является самым читаемым:
package tias;
public class Main {
private static final String NUMERIC = "123456789";
private static final String NOT_NUMERIC = "1L5C";
public static void main(String[] args) {
System.out.println(isStringNumeric(NUMERIC));
System.out.println(isStringNumeric(NOT_NUMERIC));
}
private static boolean isStringNumeric(String aString) {
if (aString == null || aString.length() == 0) {
return false;
}
for (char c : aString.toCharArray() ) {
if (!Character.isDigit(c)) {
return false;
}
}
return true;
}
}
Если Вы хотите что-то, что это горячо быстро, и у Вас есть очень четкое представление о том, какие форматы Вы хотите принять, можно создать конечный автомат DFA вручную. Это по существу, как regexes работают под капотом так или иначе, но можно избежать regex шага компиляции этот путь, и это может быть быстрее, чем универсальный regex компилятор.