Избегание класса BigInteger / больших чисел в арифметике

1

Таким образом, я выполняю некоторый материал типа арифметического типа в строке, где каждый символ получает определенное начальное значение (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);    
        }
  • 1
    Ваш вопрос совершенно неясен !!!!
  • 1
    Я согласен, что ваш вопрос неясен. Но если вы пытаетесь выяснить, как выполнить операцию % над целым числом, которое слишком велико в течение long , я советую вам придерживаться BigInteger , если только smallMod является степенью 2. smallMod и % на целых числах неопределенного размера не являются довольно сложно реализовать себя, и я уверен, что люди, которые внедрили BigInteger , приложили немало усилий и исследователей для разработки лучших алгоритмов для этой работы.
Теги:

2 ответа

0
Лучший ответ

Если вы делаете это в определенном модуле, то итерации по вашей 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;
}
  • 0
    Спасибо за ответ. проблема возникает, когда начальное значение одного из символов в строке (встречается в длинных строках) превышает long. (и я понимаю, что мне не нужен массив, но я выполнял что-то похожее с целыми числами ранее и не изменил его.)
  • 0
    Как значение char превышать размер long ?
Показать ещё 8 комментариев
0

Если результат:

long longVal = new BigInteger(stringVal).mod(new BigInteger(modulus)).longValue();

слишком велика, чтобы вписаться в long вы столкнетесь со следующим поведением, цитируя метод BigInteger # longValue в JDK:

Если этот BigInteger слишком велик, чтобы соответствовать длине, возвращаются только 64 бита младшего разряда. Обратите внимание, что это преобразование может потерять информацию об общей величине значения BigInteger, а также вернуть результат с противоположным знаком.

Поэтому вы правы, думая, что если вы попытаетесь получить long ценность от BigInteger больше, чем long вы не получите точного результата.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню