【问题标题】:Checksums - ISBN program校验和 - ISBN 程序
【发布时间】:2013-12-09 18:31:54
【问题描述】:

这个问题让我很困惑。我尝试使用这样的循环:基本上我试图从输入中获取第一个数字并执行公式,但它似乎不起作用。它看起来很简单,但我无法弄清楚。你可以帮帮我吗?谢谢。

public static int ISBN(String ninedigitNum) {
   number = 9;
   while (number > 0) {
   int nextDigit = ninedigitNum.substring(0,1);

   ...
}

校验和(来源:普林斯顿大学)。国际标准 书号 (ISBN) 是一个 10 位数的代码,用于唯一指定一本书。 最右边的数字是校验和数字,可以是唯一的 根据 d1 + 2d2 + 的条件从其他 9 位数字确定 3d3 + ... + 10d10 必须是 11 的倍数(这里 di 表示第 i 个 右数)。校验和数字 d1 可以是从 0 开始的任何值 到 10:ISBN 约定是使用值 X 来表示 10。 示例:020131452 对应的校验和位数为 5,因为是 d1 的唯一值介于 0 和 10 之间,其中 d1 + 2*2 + 3*5 + 4*4 + 5*1 + 6*3 + 7*1 + 8*0 + 9*2 + 10*0 是 11 的倍数。创建一个 Java 方法 ISBN() 将 9 位整数作为输入,计算 校验和,并返回 10 位 ISBN 号。创建 3 个 JUnit 测试 案例来测试你的方法。

我知道了,非常感谢大家!

【问题讨论】:

  • 你必须从字符串的最后一个索引开始选择每个整数。
  • 但是如何获得 10 位数字呢?我们将不得不以某种方式对其进行总结,但由于每个数字都乘以不同的数字,因此似乎很难使用循环 (d1 + 2d2 + 3d3 + ... + 10d10 )

标签: java loops object isbn


【解决方案1】:

它不起作用怎么办?无论哪种方式,我相信您缺少的是您不断获得相同的子字符串,这将是字符串的第一个数字:int nextDigit = ninedigitNum.substring(0,1);。此外,您将要使用int,而不是String;如果需要,您可以从技术上将 String 转换为 int,但问题本身需要一个 int。

有两种方法可以做到这一点。我会通过意识到 10 次方的 mod 将为您提供整数的相应数字来做到这一点,但更简单的方法是转换为 char 数组,然后直接访问。请注意,这里没有错误检查;你必须自己添加。此外,这里有很多“神奇数字”:好的代码通常很少。我建议在尝试此类问题之前学习更多数据结构;老实说,如果没有数组和链表,您几乎无法做任何事情。

char[] ISBN = ninedigitNum.toCharArray();

//Process each number
int total = 0;
for(int i=0; i<9; i++){
    int current_int = Integer.parseInt(ISBN[i]);
    total += current_int * (10 - i)
}

//Find value of d1
for(int i=0; i<9; i++){
    if(((total + i) % 11) == 0){
        total += i*100000000;
        break;
    }
}

return total;

一般情况下:使用带有System.out.println(x); 的打印输出或使用编译器的调试器来查看处理过程中发生了什么。

【讨论】:

  • 我还没有真正学习过数组,还有其他方法吗?谢谢。另外我遇到的问题是很难处理每个 int 并将其保存在某个地方,因为它是一个循环,它会做同样的事情。例如,我希望第一个数字乘以 2。如果我把它放在循环中,那不是将所有数字乘以 2 吗?因为其余的数字需要乘以 3、4、.....9 谢谢!
  • 如果你的数学比较强,你可以看看如何通过使用 10 次方的 mod (%) 值提取数字 -- x%10 = 最低位数字, x%100 = 下一个最低位,依此类推。我将以编程方式编辑答案本身的示例,但其中重要的部分是从逻辑上思考问题。关于乘法:这是数组的优点,你想把它分成单独的数字!我也很惊讶你在没有数组知识的情况下做这种问题......数组可能是掌握的最重要的数据结构。
  • 由于校验和数字是最右边的,你需要将total乘以10并加上i,还是我漏掉了什么?
  • @Chasmo:在问题描述中,出于某种原因,校验和数字似乎是第一个;或者至少,我是这么读的。但实际上,您是对的——校验和数字在数据之后,因此您只需将数字向左移动(按位左移),然后添加校验和。
【解决方案2】:

所以, 这是我写的一段代码。我仍然认为它可以提高效率。

public class Problem3 {
    public static String ISBN(String x)
    {
       char[]temp = x.toCharArray();
       int counter = 2;
       int sum = 0;
       int j=0;
       for(int i=8;i>=0;i--)
       {
           sum+= counter*Integer.parseInt(""+temp[i]);
           counter+=1;
       }
       for(j=0;j<10;j++)
       {
           if((sum+j)%11==0)
           {
               break;
           }
       }
       return x+""+j;
    }
public static void main(String args[])    
{
   String a = "020131452"; 
   System.out.println(ISBN(a));

}
}

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    这行得通:

    public static int ISBN(String nineDigitNum){
        int sum = 0;
        for(int i = 0; i<nineDigitNum.length(); i++){
            sum += Integer.parseInt(""+nineDigitNum.charAt(i))*(10-i);
        }
        return (sum%11);
    }
    

    另外我相信如果校验和是 == 到 10,它应该返回一个 X,所以你可以改变返回类型并在某处添加一个 if 语句,或者只是将 if 语句放在你使用这个方法的任何地方。

    【讨论】:

      【解决方案4】:

      这是一个短的没有循环的,只使用substring(), charAt() and length()

      public static String ISBN(String nineDigits) {
          int chkD = 11 - checkDigit(nineDigits, 0);
          return nineDigits + ((chkD == 10) ? "X" : chkD);
      }
      
      public static int checkDigit(String nDsub, int chkD) {
          if (nDsub.length() == 0)
              return 0;
          chkD = ((nDsub.charAt(0) - '0') * (nDsub.length() + 1));
          return (chkD + checkDigit(nDsub.substring(1), chkD)) % 11;
      }
      

      输出:

      > ISBN("123456789")
      "123456789X"
      > ISBN("123456780")
      "1234567806"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多