К моему (ограниченному - я вообще не разработчик C), это связано с C. Помните, что C не знает, какие классы или пространства имен есть, это всего лишь одна длинная программа.
Например, следующее должно приводить к ошибке компилятора:
void SomeFunction () {SomeOtherFunction (); } void SomeOtherFunction () {printf («Что?»); }
Ошибка должна заключаться в том, что «SomeOtherFunction не объявлен», потому что вы вызываете ее перед ее объявлением. Одним из способов его устранения является перемещение SomeOtherFunction над SomeFunction. Другой подход заключается в том, чтобы сначала объявить подпись функции:
void SomeOtherFunction (); void SomeFunction () {SomeOtherFunction (); } void SomeOtherFunction () {printf («Что?»); }
Это позволяет компилятору узнать: посмотрите где-нибудь в коде, есть функция SomeOtherFunction, которая возвращает void и не принимает никаких параметров. Итак, если вы используете код, который пытается вызвать SomeOtherFunction, не паникуйте и вместо этого ищите его.
Теперь представьте, что у вас есть SomeFunction и SomeOtherFunction в двух разных файлах .c. Затем вам нужно включить # SomeOther.c в Some.c. Теперь добавьте некоторые «частные» функции в SomeOther.c. Поскольку C не знает частных функций, эта функция будет доступна и в Some.c.
Здесь находятся файлы .h. Они определяют все функции (и переменные), которые вы хотите " Экспортировать 'из файла .c, доступ к которому можно получить в других файлах .c. Таким образом, вы получаете что-то вроде области Public / Private. Кроме того, вы можете предоставить этот файл .h для других людей, не передавая свой исходный код - файлы .h также работают с скомпилированными .lib-файлами.
Таким образом, основная причина действительно для удобства, для источника защиты кода и иметь немного развязки между частями вашего приложения.
Это было C, хотя. В C ++ введены классы и частные / общедоступные модификаторы, поэтому, хотя вы все еще можете спросить, нужны ли они, C ++ AFAIK по-прежнему требует объявления функций перед их использованием. Кроме того, многие разработчики C ++ являются или являются C devleopers, а также используют свои концепции и привычки для C ++ - зачем менять то, что не сломано?
Токенизировать строки с точкой в качестве разделителя, а затем сравнить целочисленный перевод бок о бок, начиная с левого.
Мне понравилась идея от @Peter Lawrey, и я расширил ее до дальнейших ограничений:
/ ** * Нормализовать строковый массив, * Добавляет нули, если строка из массива * имеет меньшую длину чем maxLen. ** / private Строка normalize (String [] split, int maxLen) {StringBuilder sb = new StringBuilder (""); for (String s: split) {for (int i = 0; i & lt; maxLen-s.length (); i ++) sb.append ('0'); sb.append (ы); } return sb.toString (); } / ** * Удаляет конечные нули формы '.00.0 ... 00' * (и не удаляет нули, скажем, '4.1.100') ** / public String removeTrailingZeros (String s) {int i = s.length () - 1; int k = s.length () - 1; while (i & gt; = 0 & amp; & amp; (s.charAt (i) == '.' || s.charAt (i) == '0')) {if (s.charAt (i) == ' . ') k = i-1; я--; } return s.substring (0, k + 1); } / ** * Сравнивает две версии (работает и для алфавитов), * Возвращает 1, если v1 & gt; v2, возвращает 0, если v1 == v2, * и возвращает -1, если v1 & lt; v2. ** / public int compareVersion (String v1, String v2) {// Раскомментируем ниже двух строк, если для вас, скажем, 4.1.0, равно 4.1 // v1 = removeTrailingZeros (v1); // v2 = removeTrailingZeros (v2); String [] splitv1 = v1.split ("\\."); String [] splitv2 = v2.split ("\\."); int maxLen = 0; for (String str: splitv1) maxLen = Math.max (maxLen, str.length ()); for (String str: splitv2) maxLen = Math.max (maxLen, str.length ()); int cmp = normalize (splitv1, maxLen) .compareTo (normalize (splitv2, maxLen)); return cmp & gt; 0? 1: (cmp & lt; 0 & le; -1: 0); }
Надеюсь, это поможет кому-то. Он прошел все тестовые примеры в интервьювом и литовом коде (необходимо раскомментировать две строки в функции compareVersion).
Легко протестировано!
My java Solution
public int compareVersion (String version1, String version2) {String [] first = version1.split ("\\."); String [] second = version2.split ("\\."); int len = first.length & lt; = second.length? first.length: second.length; // цикл выполняется в зависимости от того, какая короткая версия двух строк для (int i = 0; i & lt; len; i ++) {int firstInt = Integer.parseInt (first [i]); int secondInt = Integer.parseInt (второй [i]); if (firstInt & lt; secondInt) {return -1; } else if (firstInt & gt; secondInt) {return 1; }} // ниже двух условий проверьте, является ли длина не одинаковой // если длина первой строки коротка, тогда начинайте с первой строки и сравнивайте ее со вторым строковым значением. второе строковое значение не равно нулю, что означает, что оно больше. if (first.length & lt; second.length) {для (int i = first.length; i & lt; second.length; i ++) {int secondInt = Integer.parseInt (второй [i]); if (secondInt! = 0) {return -1; }}} // аналогичная логика, как указано выше, только эта первая длина на этот раз больше. else if (first.length & gt; second.length) {для (int i = second.length; i & lt; first.length; i ++) {int firstInt = Integer.parseInt (first [i]); if (firstInt! = 0) {return 1; }}} // return 0, если оба строкового значения одинаковы с возвратом 0; }
Интересно, почему все предполагают, что версии состоят только из целых чисел - в моем случае это было не так.
Зачем изобретать колесо (если версия соответствует стандарту Semver)
Сначала установите https://github.com/vdurmont/semver4j через Maven
Затем используйте эту библиотеку
Semver sem = new Semver ( "1.2.3"); sem.isGreaterThan ( "1.2.2"); // true
Pattern.compile ()
, учитывая, что ваша логика вызывается с помощью сложности O (N log N)
.
– Lukas Eder
26 February 2018 в 09:38
Написал небольшую функцию самостоятельно. Симулятор с использованием списков
public static boolean checkVersionUpdate (String oldVerison, String newVersion) {if (oldVerison.length () == 0 || newVersion.length ( ) == 0) {return false; } List & lt; String & gt; newVerList = Arrays.asList (newVersion.split ("\\.")); Список & л; Строка & GT; oldVerList = Arrays.asList (oldVerison.split ("\\.")); int diff = newVerList.size () - oldVerList.size (); Список & л; Строка & GT; newList = new ArrayList & lt; & gt; (); if (diff & gt; 0) {newList.addAll (oldVerList); for (int i = 0; i & lt; diff; i ++) {newList.add ("0"); } return examArray (newList, newVerList, diff); } else if (diff & lt; 0) {newList.addAll (newVerList); for (int i = 0; i & lt; -diff; i ++) {newList.add ("0"); } return examArray (oldVerList, newList, diff); } else {return studyArray (oldVerList, newVerList, diff); }} public static boolean studyArray (List & lt; String & gt; oldList, List & lt; String & gt; newList, int diff) {boolean newVersionGreater = false; for (int i = 0; i & lt; oldList.size (); i ++) {if (Integer.parseInt (newList.get (i)) & gt; Integer.parseInt (oldList.get (i))) {newVersionGreater = true ; ломать; } else if (Integer.parseInt (newList.get (i)) & lt; Integer.parseInt (oldList.get (i))) {newVersionGreater = false; ломать; } else {newVersionGreater = diff & gt; 0; }} return newVersionGreater; }
Давайте будем честными, Лексикографическое сравнение String
будет очень хорошо работать в большинстве случаев.
"1.0.0" .compareTo ("1.0.1" ) // -1
Возможна некоторая ошибка, если, например, у нас есть некоторое форматирование в некоторой версии
"1.01.1" .compareTo ( «1.1.0») // -1 должно быть 1
Это можно легко исправить, очистив эти значения и, конечно, предоставив некоторые простые методы.
public class Version реализует Comparable & lt; Version & gt; {private static final String sanitizeRegex = ".0 ([1-9] +)"; private String value; public Version (String value) {if (value == null) throw new IllegalArgumentException («Версия нуждается в допустимом значении»); this.value = значение.replaceAll (sanitizeRegex, ". $ 1"); } public boolean isLessThan (Версия o) {return this.compareTo (o) & lt; 0; } public boolean isGreaterThan (Версия o) {return this.compareTo (o) & gt; 0; } public boolean isEquals (Версия o) {return this.compareTo (o) == 0; } @Override public int compareTo (Версия o) {return this.value.compareTo (o.value); } @Override public String toString () {возвращаемое значение; }}
Регулярное выражение удалит, если необходимо, удаление ведущего 0
.
01 - & gt; 1 0 - & gt; 0 00 - & gt; 0 10 - & gt; 10
Это позволяет нам иметь довольно простое сравнение, используя то, что уже существует.
Быстрый тестовый пример, взятый из Ответ Йохана Пола [ ! d13]
System.out.println (новая версия («1.2»). isGreaterThan (новая версия («1.1»))); // true System.out.println (новая версия («1.2.1»). isGreaterThan (новая версия («1.1.2»)); // true System.out.println (новая версия («1.1.1»). isGreaterThan (новая версия («1.1.1»)); // false System.out.println (новая версия («1.1.1»). isGreaterThan (новая версия («1.1»)); // true System.out.println (новая версия («1.1.0»). isGreaterThan (новая версия («1.1»)); // true System.out.println (новая версия («1.1-RC2»). isGreaterThan (новая версия («1.1-RC1»)); // true System.out.println (новая версия («1.1-RC1»). isGreaterThan (новая версия («1.1»)); // true System.out.println (новая версия («1.0.1»). isGreaterThan (новая версия («1.1»)); // false
Вот оптимизированная реализация:
public static final Comparator & lt; CharSequence & gt; VERSION_ORDER = new Comparator & lt; CharSequence & gt; () {@Override public int compare (CharSequence lhs, CharSequence rhs) {int ll = lhs.length (), rl = rhs.length (), lv = 0, rv = 0, li = 0, ri = 0; char c; do {lv = rv = 0; while (-ll & gt; = 0) {c = lhs.charAt (li ++); если (c & lt; '0' || c & gt; '9') break; lv = lv * 10 + c - '0'; } while (-rl & gt; = 0) {c = rhs.charAt (ri ++); если (c & lt; '0' || c & gt; '9') break; rv = rv * 10 + c - '0'; }} while (lv == rv & amp; & amp; (ll & gt; = 0 || rl & gt; = 0)); return lv - rv; }};
Результат:
"0.1" - "1.0" = -1 "1.0" - "1.0" = 0 "1.0" - "1.0.0 "= 0" 10 "-" 1.0 "= 9" 3.7.6 "-" 3.7.11 "= -5" foobar "-" 1.0 "= -1
public int compare (String v1, String v2) {v1 = v1.replaceAll ("\\ s", ""); v2 = v2.replaceAll ("\\ s", ""); String [] a1 = v1.split ("\\."); String [] a2 = v2.split ("\\."); Список & л; Строка & GT; l1 = Arrays.asList (a1); Список & л; Строка & GT; l2 = Arrays.asList (a2); int i = 0; while (true) {Double d1 = null; Двойной d2 = null; try {d1 = Double.parseDouble (l1.get (i)); } catch (IndexOutOfBoundsException e) {} try {d2 = Double.parseDouble (l2.get (i)); } catch (IndexOutOfBoundsException e) {} if (d1! = null & amp; d2! = null) {if (d1.doubleValue () & gt; d2.doubleValue ()) {return 1; } else if (d1.doubleValue () & lt; d2.doubleValue ()) {return -1; }} else if (d2 == null & amp; & amp; d1! = null) {if (d1.doubleValue () & gt; 0) {return 1; }} else if (d1 == null & amp; d2! = null) {if (d2.doubleValue () & gt; 0) {return -1; }} else {break; } i ++; } return 0; }
public static int compareVersions (String version1, String version2) {String [] levels1 = version1.split ("\\."); String [] levels2 = version2.split ("\\."); int length = Math.max (levels1.length, levels2.length); for (int i = 0; i & lt; length; i ++) {Integer v1 = i & lt; levels1.length? Integer.parseInt (levels1 [i]): 0; Целое число v2 = i & lt; levels2.length? Integer.parseInt (levels2 [i]): 0; int compare = v1.compareTo (v2); if (compare! = 0) {return compare; }} return 0; }
Это очень просто, используя Maven:
import org.apache.maven.artifact.versioning.DefaultArtifactVersion; DefaultArtifactVersion minVersion = new DefaultArtifactVersion ("1.0.1"); DefaultArtifactVersion maxVersion = new DefaultArtifactVersion ("1.10"); DefaultArtifactVersion version = new DefaultArtifactVersion ("1.11"); if (version.compareTo (minVersion) & lt; 0 || version.compareTo (maxVersion) & gt; 0) {System.out.println («Извините, ваша версия не поддерживается»); }
Вы можете получить правильную строку зависимостей для Maven Artifact с этой страницы :
& lt; dependency & gt; & Lt; идентификатор_группа & GT; org.apache.maven & л; / идентификатор_группа & GT; & Lt; артефакт & GT; Maven-артефакт, & л; / артефакт & GT; & Lt; & версии GT; 3.0.3 & л; / & версии GT; & Lt; / зависимость & GT;
Comparable.compareTo
документируется как возвращающее «отрицательное целое число, ноль или положительное целое число», поэтому неплохо избегать проверки на -1 и +1.
– seanf
18 November 2014 в 07:22
Этот код пытается решить этот тип версий сравнения.
Большинство спецификаторов версии, например> = 1.0, не требуют пояснений. Спецификатор ~> имеет особое значение, лучше всего показано на примере. ~> 2.0.3 идентична> = 2.0.3 и & lt; 2.1. ~> 2.1 совпадает с> = 2.1 и & lt; 3.0.
blockquote>public static boolean apply (String cmpDeviceVersion, String reqDeviceVersion) {Boolean equal =! CmpDeviceVersion.contains ("& gt;") & amp; & amp; & amp; & amp; & amp; ! cmpDeviceVersion.contains ("& gt; =") & amp; & amp; & amp; ! cmpDeviceVersion.contains ("& lt;") & amp; & amp; & amp; ! cmpDeviceVersion.contains ("& lt; =") & amp; & amp; & amp; ! CmpDeviceVersion.contains ( "~ & GT;"); Boolean между = cmpDeviceVersion.contains ("~ & gt;"); Boolean higher = cmpDeviceVersion.contains ("& gt;") & amp; & amp; & amp; ! cmpDeviceVersion.contains ("& gt; =") & amp; & amp; & amp; ! CmpDeviceVersion.contains ( "~ & GT;"); Boolean higherOrEqual = cmpDeviceVersion.contains ("& gt; ="); Boolean less = cmpDeviceVersion.contains ("& lt;") & amp; & amp; & amp; ! CmpDeviceVersion.contains ( "& л; ="); Boolean lessOrEqual = cmpDeviceVersion.contains ("& lt; ="); cmpDeviceVersion = cmpDeviceVersion.replaceAll ("[& lt; gt; = ~]", ""); cmpDeviceVersion = cmpDeviceVersion.trim (); String [] version = cmpDeviceVersion.split ("\\."); String [] reqVersion = reqDeviceVersion.split ("\\."); if (равно) {return isEqual (версия, reqVersion); } else if (между) {return isBetween (version, reqVersion); } else if (higher) {return isHigher (version, reqVersion); } else if (higherOrEqual) {return isEqual (version, reqVersion) || isHigher (версия, reqVersion); } else if (less) {return isLess (версия, reqVersion); } else if (lessOrEqual) {return isEqual (version, reqVersion) || isLess (версия, reqVersion); } return false; } private static boolean isEqual (String [] version, String [] reqVersion) {String strVersion = StringUtils.join (версия); String strReqVersion = StringUtils.join (reqVersion); if (version.length & gt; reqVersion.length) {Integer diff = version.length - reqVersion.length; strReqVersion + = StringUtils.repeat (". 0", diff); } else if (reqVersion.length & gt; version.length) {Integer diff = reqVersion.length - version.length; strVersion + = StringUtils.repeat (". 0", diff); } return strVersion.equals (strReqVersion); } private static boolean isHigher (String [] version, String [] reqVersion) {String strVersion = StringUtils.join (версия); String strReqVersion = StringUtils.join (reqVersion); if (version.length & gt; reqVersion.length) {Integer diff = version.length - reqVersion.length; strReqVersion + = StringUtils.repeat (". 0", diff); } else if (reqVersion.length & gt; version.length) {Integer diff = reqVersion.length - version.length; strVersion + = StringUtils.repeat (". 0", diff); } return strReqVersion.compareTo (strVersion) & gt; 0; } private static boolean isLess (String [] version, String [] reqVersion) {String strVersion = StringUtils.join (версия); String strReqVersion = StringUtils.join (reqVersion); if (version.length & gt; reqVersion.length) {Integer diff = version.length - reqVersion.length; strReqVersion + = StringUtils.repeat (". 0", diff); } else if (reqVersion.length & gt; version.length) {Integer diff = reqVersion.length - version.length; strVersion + = StringUtils.repeat (". 0", diff); } return strReqVersion.compareTo (strVersion) & lt; 0; } private static boolean isBetween (String [] version, String [] reqVersion) {return (isEqual (version, reqVersion) || isHigher (version, reqVersion)) & amp; & amp; & amp; & amp; & amp; & amp; isLess (getNextVersion (версия), reqVersion); } private static String [] getNextVersion (String [] version) {String [] nextVersion = new String [version.length]; for (int i = version.length - 1; i & gt; = 0; i--) {if (i == version.length - 1) {nextVersion [i] = "0"; } else if ((i == version.length - 2) & amp; NumberUtils.isNumber (version [i])) {nextVersion [i] = String.valueOf (NumberUtils.toInt (версия [i]) + 1) ; } else {nextVersion [i] = версия [i]; }} return nextVersion; }
для моих проектов Я использую свою библиотеку commons-version https://github.com/raydac/commons-version , она содержит два вспомогательных класса - для синтаксического анализа версии (анализируемая версия может быть сравнена с другой , потому что он сопоставим) и VersionValidator, который позволяет проверять версию для некоторого выражения, такого как ! = ide-1.1.1, & gt; идея-1.3.4-SNAPSHOT; & lt; 1.2.3
[ ! d2]
Для Scala вы можете использовать библиотеку, которую я создал: https://github.com/kypeli/sversion
Версия ("1.2") & gt; Версия ("1.1") // true Version ("1.2.1") & gt; Версия ("1.1.2") // true Version ("1.1.1") == Version ("1.1.1") // true Version ("1.1.1") & gt; Версия ("1.1") // true Version ("1.1.0") == Версия ("1.1") // true Version ("1.1-RC2") & gt; Версия («1.1-RC1») // истинная версия («1.1-RC1») & gt; Версия ("1.1") // true
Вам нужно нормализовать строки версии, чтобы их можно было сравнить. Что-то вроде
import java.util.regex.Pattern; public class Main {public static void main (String ... args) {compare ("1.0", "1.1"); сравнить («1.0.1», «1.1»); сравнить («1.9», «1.10»); сравнить («1.a», «1.9»); } private static void compare (String v1, String v2) {String s1 = normalisedVersion (v1); Строка s2 = нормализованная версия (v2); int cmp = s1.compareTo (s2); Строка cmpStr = cmp & lt; 0? "& Л;" : cmp & gt; 0? "& GT;" : "=="; System.out.printf ("'% s'% s '% s'% n", v1, cmpStr, v2); } public static String normalizedVersion (String version) {return normalisedVersion (версия, ".", 4); } public static String normalizedVersion (String version, String sep, int maxWidth) {String [] split = Pattern.compile (sep, Pattern.LITERAL) .split (версия); StringBuilder sb = new StringBuilder (); for (String s: split) {sb.append (String.format ("%" + maxWidth + 's', s)); } return sb.toString (); }}
Печатает
blockquote>'1.0' & lt; '1.1' '1.0.1' & lt; '1,1' '1,9' '1.10' '1.a' & gt; '1.9'
Я создал простую утилиту для сравнения версий на платформе Android, используя соглашение Semantic Versioning . Поэтому он работает только для строк в формате X.Y.Z (Major.Minor.Patch), где X, Y и Z - целые неотрицательные числа. Вы можете найти его на моем GitHub .
Метод Version.compareVersions (String v1, String v2) сравнивает две строки версии. Он возвращает 0, если версии равны, 1, если версия v1 до версии v2, -1, если версия v1 находится после версии v2, -2, если формат версии недействителен.
Лучшее для повторного использования существующего кода, возьмите класс Maven ComparableVersion
:
Не включать зависимость от maven-артефакта как который будет вытягивать различные транзитивные зависимости
assertTrue (новая ComparableVersion («1.1-BETA»). CompareTo (новая ComparableVersion («1.1-RC»)) & lt; 0)
– Fabian Kessler
17 March 2015 в 22:49
общедоступный класс VersionComparator {/ * цикл через обе строки версии *, а затем проведите внутреннюю строку к компьютеру значение val для int * для каждого целого числа read, do num * 10 + & lt; integer read & gt; * и остановитесь, когда натыкаетесь на. * Когда '.' встречается ... * см. if '.' встречается для обеих строк *, если он затем сравнивает num1 и num2 *, если num1 == num2 ... итерация по p1 ++, p2 ++ * else return (num1 & gt; num2)? 1: -1 * Если оба конца строки затем сравнивают (num1, num2), возвращают 0, 1, -1 * else, перебирают более длинную строку и * проверяют, имеют ли они только завершающие нули. * Если у нее есть только завершающие нули, тогда возвращаем 0 * else это больше, чем другая строка * / public static int compareVersions (String v1, String v2) {int num1 = 0; int num2 = 0; int p1 = 0; int p2 = 0; while (p1 & lt; v1.length () & amp; p2 & lt; v2.length ()) {num1 = Integer.parseInt (v1.charAt (p1) + ""); num2 = Integer.parseInt (v2.charAt (p2) + ""); p1 ++; p2 ++; (p1 & lt; v1.length () & amp; p2 & lt; v2.length () & amp; v1.charAt (p1)! = '.' & amp; v2.charAt (p2)! = ' . ') {if (p1 & lt; v1.length ()) num1 = num1 * 10 + Integer.parseInt (v1.charAt (p1) + ""); if (p2 & lt; v2.length ()) num2 = num2 * 10 + Integer.parseInt (v2.charAt (p2) + ""); p1 ++; p2 ++; } if (p1 & lt; v1.length () & amp; p2 & lt; v2.length () & amp; v1.charAt (p1) == '.' & amp; v2.charAt (p2) == '.') {if ((num1 ^ num2) == 0) {p1 ++; p2 ++; } else return (num1 & gt; num2)? 1: -1; } else if (p1 & lt; v1.length () & amp; p2 & lt; v2.length () & amp; v1.charAt (p1) == '.') return -1; else if (p1 & lt; v1.length () & amp; p2 & lt; v2.length () & amp; v2.charAt (p2) == '.') return 1; } if (p1 == v1.length () & amp; p2 == v2.length ()) {if ((num1 ^ num2) == 0) return 0; else return (num1 & gt; num2)? 1: -1; } else if (p1 == v1.length ()) {if ((num1 ^ num2) == 0) {while (p2 & lt; v2.length ()) {if (v2.charAt (p2)! = '. '& amp; v2.charAt (p2)! =' 0 ') return -1; p2 ++; } return 0; } else return (num1 & gt; num2)? 1: -1; } else {if ((num1 ^ num2) == 0) {while (p1 & lt; v1.length ()) {if (v1.charAt (p1)! = '.' & amp; v1.charAt (p1) ! = '0') return 1; p1 ++; } return 0; } else return (num1 & gt; num2)? 1: -1; }} public static void main (String [] args) {System.out.println (compareVersions ("11.23", "11.21.1.0.0.1.0") ^ 1); System.out.println (compareVersions ("11.21.1.0.0.1.0", "11.23") ^ -1); System.out.println (compareVersions ("11.23", "11.23.0.0.0.1.0") ^ -1); System.out.println (compareVersions ("11.2", "11.23") ^ -1); System.out.println (compareVersions ("11.23", "11.21.1.0.0.1.0") ^ 1); System.out.println (compareVersions ("1.21.1.0.0.1.0", "2.23") ^ -1); System.out.println (compareVersions ("11.23", "11.21.1.0.0.1.0") ^ 1); System.out.println (compareVersions ("11.23.0.0.0.0.0", "11.23") ^ 0); System.out.println (compareVersions ("11.23", "11.21.1.0.0.1.0") ^ 1); System.out.println (compareVersions ("1.5.1.3", "1.5.1.3.0") ^ 0); System.out.println (compareVersions ("1.5.1.4", "1.5.1.3.0") ^ 1); System.out.println (compareVersions ("1.2.1.3", "1.5.1.3.0") ^ -1); System.out.println (compareVersions ("1.2.1.3", "1.22.1.3.0") ^ -1); System.out.println (compareVersions ("1.222.1.3", "1.22.1.3.0") ^ 1); }}