算术中避免使用BigInteger类/大数

时间:2015-03-25 06:12:24

标签: java

所以我在字符串上执行一些mod算术类型的东西,其中每个char获得一个特定的初始值(在其ascii上展开)并在字符串中定位。这些数字变得非常大,因为它们的初始值为(ascii)*26^charPos。值得注意的是,数字字符只将其值(0-9)添加到总数中;

有没有办法避免使用BigInt类(因为我只对(intialVal)%(relatively small number))感兴趣我想你可以使用通常的

value += val;
  if(value >= mod)
   value = value % mod;

但这只能在排序的整数列表中起作用,并且也不能解决单个字符何时通过使用上述字符值公式生成BigInt的问题。我确定可以使用mod操作符完成某些操作。

放在一边; 如果bigNum超过long(或int,无论foo如声明的那样)的大小,算法都不会正常运行吗?

int(or long) foo = BigNum(possibly bigger than long) % smallMod;

我意识到我可以声明几个BigInteger对象,只是将所有值添加到totalValue然后对总计执行最终的mod操作,但是如果可能的话,我会避免使用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); 
}

编辑****回应David Wallace的回答

对不起,我重读了你的解释,我明白你在做什么......你的回答正是我所得到的。我只是在处理字符是一个数字的情况下遇到麻烦,因为它只添加数值而不是乘以26 ^ pos。我保持数值的运行总数,以便将它添加到最终答案(以及如果它超过mod值再次修改它)但我不知道如何增加适当的功率一个。我可能错过了很明显的东西。评论的代码是我尝试解决这个问题的一半。

    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);    
        }

2 个答案:

答案 0 :(得分:0)

如果结果:

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

太大而不适合long您会遇到以下行为,引用JDK中的BigInteger#longValue方法:

  

如果这个BigInteger太大而不适合长,只返回低位64位。请注意,此转换可能会丢失有关BigInteger值的总体大小的信息,并返回具有相反符号的结果。

因此,如果您尝试从long大于BigInteger获得long值,那么您将无法获得准确的结果。

答案 1 :(得分: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;
}