Почему оператор xor выдает сообщение об ошибке «Нет подписи метода» и / или в каком формате bitCount () должен быть проходимым? - PullRequest
0 голосов
/ 02 сентября 2018

Я пытался преобразовать функцию SQL в Groovy для использования в Elastisearch. Но мои знания java и groovy равны нулю, и я боролся со всеми ошибками по мере их появления.

Первая проблема с convertFromBaseToBase работой была решена здесь . Но сейчас у меня проблемы с оператором XOR .

Вполне возможно, что после xor будет больше проблем, поэтому я выложу полный код заранее:

public static String convertFromBaseToBase (String str, int fromBase, int toBase){
  return (new BigInteger(str, fromBase)).toString(toBase);
}

def ih_comparehash (String hash_1, String hash_2, int maxlen) { 

    String hashpart1;
    String hashpart2;

    int bitcnt = 0
    int strlen = 16
    int len = 0

    len = hash_1.length() / strlen

    for (i = 0; i < len && i < maxlen; i++) {

        hashpart1 = hash_1.substring((i * strlen) + 1, strlen);
        hashpart2 = hash_2.substring((i * strlen) + 1, strlen);

        cfbtb_1 = convertFromBaseToBase(hashpart1, 16, 10);
        cfbtb_2 = convertFromBaseToBase(hashpart2, 16, 10);

        bitcnt = bitcnt + (cfbtb_1 ^ cfbtb_2).bitCount();
    }

    return ((64 * i) - bitcnt) * 100.0 / (64 * i);
}

System.out.print(ih_comparehash("8f8f87878f8f8080", "50b0f878787a9f97", 1));

Pokable по адресу: https://groovyconsole.appspot.com/script/5119420292661248

Текущая ошибка:

groovy.lang.MissingMethodException: Нет сигнатуры метода: java.lang.Long.bitCount () применим для типов аргументов: () значения: []
Возможные решения: bitCount (long)
на Script1.ih_comparehash (Script1.groovy: 31)
at Script1 $ ih_comparehash.callCurrent (неизвестный источник)
на Script1.run (Script1.groovy: 40)

Если я что-то упустил, вот функция из SQL, которую я пытаюсь преобразовать в Groovy:

BEGIN
    DECLARE hashpart1 varchar(64) DEFAULT "";
    DECLARE hashpart2 varchar(64) DEFAULT "";
    DECLARE bitcnt int DEFAULT 0;
    DECLARE strlen int DEFAULT 16;
    DECLARE i int DEFAULT 0;
    DECLARE len int DEFAULT 0;

    SET len = LENGTH(hash1) / strlen;

    WHILE i<len AND i < maxlen DO
        SET hashpart1 = SUBSTRING(hash1,(i*strlen)+1,strlen);
        SET hashpart2 = SUBSTRING(hash2,(i*strlen)+1,strlen);
        SET bitcnt = bitcnt + bit_count(cast(conv(hashpart1, 16, 10) as unsigned) ^ cast(conv(hashpart2, 16, 10) as unsigned));
        SET i = i+1;
    END WHILE;

    RETURN ((64*i)-bitcnt)*100.0/(64*i);
END

1 Ответ

0 голосов
/ 02 сентября 2018

Код SQL обрабатывает фрагменты из 16 шестнадцатеричных цифр, поскольку это ограничивает длину числовых значений, используемых в выражениях, до 64-битных чисел.

Затем он преобразует 16-значное шестнадцатеричное число в основание-10, поэтому он может привести к unsigned, выполнить XOR и выполнить битовый подсчет. XOR - это двоичная операция, поэтому base-10 выполняется только для приведения и фактически не требуется, если в SQL была функция для разбора шестнадцатеричных чисел.

В Java существует класс с именем BigInteger (вы на самом деле его используете), который может обрабатывать числа любой длины, поэтому все это можно сделать так:

public double ih_comparehash(String hash_1, String hash_2, int maxlen) {
    int len = Math.min(hash_1.length() / 16, maxlen);
    BigInteger num1 = new BigInteger(hash_1.substring(0, 16 * len), 16);
    BigInteger num2 = new BigInteger(hash_2.substring(0, 16 * len), 16);
    int bitcnt = num1.xor(num2).bitCount();
    return ((64 * len) - bitcnt) * 100.0 / (64 * len);
}

Или эквивалентный Groovy-код, если вы предпочитаете.

...