Таким образом, я выполняю некоторый материал типа арифметического типа в строке, где каждый символ получает определенное начальное значение (depnding on its ascii) и позицию в строке. эти числа становятся довольно большими, так как их начальное значение (ascii)*26^charPos
. стоит отметить, что числовые символы только добавляют свое значение (0-9) к сумме;
есть ли способ избежать использования класса BigInt (поскольку im интересуется только (intialVal)%(relatively small number))
я полагаю, вы могли бы использовать обычный
value += val;
if(value >= mod)
value = value % mod;
но это будет работать только в отсортированном списке целых чисел, а также не решит проблему того, когда один символ генерирует BigInt, используя приведенную выше формулу для значения символа. im уверен, что что-то может быть сделано с помощью оператора мод.
как в сторону; арифметика не получится правильно, если bigNum превышает размер длинного (или int, независимо от того, что foo является объявленным как) правильно?
int(or long) foo = BigNum(possibly bigger than long) % smallMod;
я понимаю, что могу объявить несколько объектов BigInteger и просто добавить все значения в totalValue, а затем выполнить окончательную операцию mod на сумме, но id скорее избежит этого, если это возможно, поскольку арифметика BigInteger - это то, что я не использовал много (и это просто похоже на боль в заднице и вообще не нужна в этом случае). Я знаю, что будет много подходов, но я бы не прочь услышать разные взгляды. заранее спасибо.
Вот какой код я придумал, когда срабатывает длинный порог,
public static void main(String[] args) {
String str = "st4ck0ver";
char[] x = str.toCharArray();
long value = 0;
int mod = 87;
for(int i = 0; i < x.length; i++) {
long val;
int charVal;
int exp = x.length - (i+1);
if((int)x[i] < 58) {
charVal = (int)x[i] - 48;
val = charVal;
}
else{
charVal = (int)x[i]- 96;
val = (long) (charVal * Math.pow(26, exp));
}
value += val;
System.out.println("exp:" + exp + ", char:" + x[i] + ", "
+ ", charValue:" + charVal + " value:" + val + ", curr total value:" + value);
}
value %= mod;
System.out.println("Final value:" + value);
}
EDIT **** в ответ на ответ Дэвида Уоллеса
Мне жаль, я перечитываю ваше объяснение, и я понимаю, что вы делаете. Ваш ответ был именно тем, к чему я обращался. им просто приходится иметь дело с случаем, когда символ является числом, поскольку он только добавляет численное значение вместо того, чтобы умножить его на 26 ^ поз. ive сохранила текущую итоговую величину для числовых значений, чтобы добавить ее к окончательному ответу (а также модифицировать ее снова, если она превышает значение мод), но я не могу понять, как увеличить соответствующую мощность на единицу. Я, вероятно, пропустил что-то совершенно очевидное. прокомментированный код - моя половина попытки решить эту проблему.
public static void main(String[] args) {
//String str = "st4ck0ver";
//String str = "hello";
String str = "time2go";
char[] x = str.toCharArray();
int mod = 2004;
int answer = 0;
int power = 1;
int numericalVal = 0;
//int skipPower;
for (int i = x.length - 1; i >=0; i--) {
int charVal;
if((int)x[i] < 58) {
charVal = (int)x[i] - 48;
numericalVal += charVal;
//skipPower++; //perhaps need to use something like this?
//
} // down
else { // in here somewhere
charVal = (int)x[i]- 96;
answer += ( charVal * power);
answer %= mod;
power *= 26;
power %= mod;
//skipPower = 0; //reset skipPower in case it was used
}
}
//answer += numericalVal;
//if(answer + numericalVal >= mod)
// answer %= mod;
System.out.println("Final value:" + answer);
}
Если вы делаете это в определенном модуле, то итерации по вашей String
, отслеживая общее количество требуемого значения в этом модуле и значение соответствующей мощности 26, также в этом модуле. Если модуль очень мал, как вы заявляете, тогда int
должен быть адекватным для каждого из них.
Обратите внимание, что я предположил, что ваша String
состоит только из строчных букв здесь. Исправьте это, если вам нужно.
int answer = 0;
int power = 1;
for (int i = 0; i < inputString.length(); i++) {
int charValue = inputString.charAt(i) - 'a';
answer += ( charValue * power );
answer %= mod;
power *= 26;
power %= mod;
}
редактировать
Размещение редакций OP, показывающих, что String
должна быть перемещена в обратном порядке, а значение места не принимается во внимание, когда встречается цифра, код, вероятно, должен быть следующим.
int answer = 0;
int power = 1;
for (int i = inputString.length() - 1; i >=0; i--) {
if(inputString.charAt( i ) < 58) {
int charValue = inputString.charAt( i ) - 48;
answer += charValue;
}
else {
int charValue = inputString.charAt( i ) - 96;
answer += ( charValue * power );
}
answer %= mod;
power *= 26;
power %= mod;
}
char
превышать размер long
?
Если результат:
long longVal = new BigInteger(stringVal).mod(new BigInteger(modulus)).longValue();
слишком велика, чтобы вписаться в long
вы столкнетесь со следующим поведением, цитируя метод BigInteger # longValue в JDK:
Если этот BigInteger слишком велик, чтобы соответствовать длине, возвращаются только 64 бита младшего разряда. Обратите внимание, что это преобразование может потерять информацию об общей величине значения BigInteger, а также вернуть результат с противоположным знаком.
Поэтому вы правы, думая, что если вы попытаетесь получить long
ценность от BigInteger
больше, чем long
вы не получите точного результата.
%
над целым числом, которое слишком велико в течениеlong
, я советую вам придерживатьсяBigInteger
, если толькоsmallMod
является степенью 2.smallMod
и%
на целых числах неопределенного размера не являются довольно сложно реализовать себя, и я уверен, что люди, которые внедрилиBigInteger
, приложили немало усилий и исследователей для разработки лучших алгоритмов для этой работы.