gpt4 book ai didi

plsql - 在 PL/SQL 中计算大数的模数

转载 作者:行者123 更新时间:2023-12-04 20:08:59 24 4
gpt4 key购买 nike

我正在尝试在 PL/SQL 中计算大模数。我实现了一个在这个位置找到的方法:http://en.wikipedia.org/wiki/International_Bank_Account_Number在 IBAN 上的模运算下。但是当我使用这个数字时,我得到了错误的结果:221021290110000123452229211210282900128222984。

这是该方法需要完成的方式:

分段计算 D mod 97 可以通过多种方式完成。一种这样的方法如下:

  • 从 D 的最左边数字开始,用前 9 位数字构造一个数,称其为 N。
  • 计算 N mod 97。如果结果小于 10,则在结果前面加上 0,给出 00 到 96 范围内的结果。
  • 通过将上述结果(步骤 2)与 D 的下 7 个数字连接起来,构造一个新的 9 位 N。如果 D 中剩余的数字少于 7 个,但至少有一个,则构造一个新的 N,它将小于 9数字,来自上述结果(步骤 2),后跟 D
  • 的其余数字
  • 重复步骤 2-3,直到处理完 D 的所有数字

  • 步骤 2 中最终计算的结果将是 D mod 97 = N mod 97。

    我做了一些日志记录,这些是所有取模步骤的结果:
    221021290110000123452229211210282900128222984 (221021290 % 97 = 0)
    00110000123452229211210282900128000000 (001100001 % 97 = 21)
    2123452229211210282900128000000 (212345222 & 97 = 0)
    009211210282900128000000 (009211210 % 97 = 90)
    90282900128000000 (902829001 % 97 = 46)
    4628000000 (462800000 % 97 = 2)
    020 = 20

    结果必须是 1。我用模计算器检查了它,它必须是 1。对于大多数数字,计算器是正确的。

    这是我制作的代码,这个数字怎么可能不正确:
    create or replace function doubleDiget (iban number)
    return varchar2
    as
    begin
    if(iban <= 9) then
    return concat('0',iban);
    else
    return iban;
    end if;
    end doubleDiget;

    create or replace FUNCTION modbig (iban number)
    RETURN varchar2
    AS
    lengthIban number(38);
    modUitkomts number(38);
    modUitkomtsc varchar(38);
    restIban varchar(38);
    modlength number(38);
    BEGIN

    modUitkomts := SUBSTR(iban,0,9) mod 97;
    modUitkomtsc := doubleDiget(modUitkomts);
    restIban := concat(modUitkomtsc,SUBSTR(iban,10));
    dbms_output.put_line(restIban);

    loop
    if( length(restIban) >= 9) then
    modUitkomts := SUBSTR(restIban,0,9) mod 97;
    modUitkomtsc := doubleDiget(modUitkomts);
    restIban := concat(modUitkomtsc,SUBSTR(restIban,10));
    dbms_output.put_line(restIban);
    else
    exit;
    end if;
    end loop;

    modUitkomts := restIban mod 97;
    return modUitkomts;


    END modbig;

    begin
    DBMS_OUTPUT.PUT_LINE(modbig(221021290110000123452229211210282900128222984));
    end;

    最佳答案

    使用 VARCHAR2而不是 NUMBER :

    SQL> DECLARE
    2 FUNCTION modbig(iban VARCHAR2) RETURN VARCHAR2 IS -- won't be rounded
    3 lengthIban NUMBER(38);
    4 modUitkomts NUMBER(38);
    5 modUitkomtsc VARCHAR(38);
    6 restIban VARCHAR(50);
    7 modlength NUMBER(38);
    8 BEGIN
    9 restIban := iban;
    10 modUitkomts := SUBSTR(restIban, 0, 9) MOD 97;
    11 modUitkomtsc := LPAD(modUitkomts, 2, '0');
    12 restIban := concat(modUitkomtsc, SUBSTR(iban, 10));
    13
    14 LOOP
    15 IF (length(restIban) >= 9) THEN
    16 modUitkomts := SUBSTR(restIban, 0, 9) MOD 97;
    17 modUitkomtsc := LPAD(modUitkomts, 2, '0');
    18 restIban := concat(modUitkomtsc, SUBSTR(restIban, 10));
    19 ELSE
    20 EXIT;
    21 END IF;
    22 END LOOP;
    23 modUitkomts := restIban MOD 97;
    24 RETURN modUitkomts;
    25 END modbig;
    26
    27 BEGIN
    28 DBMS_OUTPUT.PUT_LINE(
    29 modbig('221021290110000123452229211210282900128222984')); -- varchar2
    30 END;
    31 /
    1
    PL/SQL procedure successfully completed

    说明: NUMBER dataype 的精度约为 38 位,所以这个 将被四舍五入 对于非常大的数字,因此您的输出以 0000 结尾而不是您输入的数字。

    关于plsql - 在 PL/SQL 中计算大数的模数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20908107/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com