V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yangyuhan12138
V2EX  ›  程序员

oracle 1000 的阶乘 最后输出字符串

  •  
  •   yangyuhan12138 · 2023-01-10 18:47:24 +08:00 · 2220 次点击
    这是一个创建于 677 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有没有 v 友 公司正好有 oracle 字符串相乘的函数 非常大的整数字符串相乘 最后结果输出为字符串 要是有阶乘的代码分享一下更好🙏

    19 条回复    2023-01-12 11:20:01 +08:00
    falsemask
        1
    falsemask  
       2023-01-10 18:54:25 +08:00
    java 的话可以直接用 BigDecimal
    falsemask
        2
    falsemask  
       2023-01-10 18:54:44 +08:00
    @falsemask 不好意思,没看到 oracle
    yangyuhan12138
        3
    yangyuhan12138  
    OP
       2023-01-10 18:55:19 +08:00
    @falsemask Java 我就没那么难受了 oracle 这边语法不熟悉 主要是
    lixiang2017
        4
    lixiang2017  
       2023-01-10 19:08:30 +08:00 via Android
    感觉自己模拟也不麻烦
    yangyuhan12138
        6
    yangyuhan12138  
    OP
       2023-01-10 23:45:52 +08:00
    @Alias4ck 数据会十分的大 不可能用简单的乘法 只能按位相乘再相加 并且使用字符串储存结果
    Alias4ck
        7
    Alias4ck  
       2023-01-11 01:03:43 +08:00
    @yangyuhan12138 首先你这个问题 肯定是一个 profile 的问题 ,你都没验证测试过 就说不可能 多大是多大?( stackoverflow 上的答案 也是别人的实践解决方案啊
    jmc891205
        8
    jmc891205  
       2023-01-11 07:37:06 +08:00
    Karatsuba algorithm [1]
    自己实现一下

    [1]: https://en.wikipedia.org/wiki/Karatsuba_algorithm
    mringg
        9
    mringg  
       2023-01-11 08:26:09 +08:00 via iPhone
    阶乘就暴力点吧,把数据先算好,存数据库,之后查表吧。
    shakoon
        10
    shakoon  
       2023-01-11 08:36:26 +08:00
    这种跟数据库查询已经没有任何关系了的运算,不建议用数据库来做,不然效率堪忧。
    建议找一个现成的 java 阶乘代码来嵌进 oracle 使用。oracle 很早以前就支持 java 嵌入的,而且有好几种方式可以调用。
    cccer
        11
    cccer  
       2023-01-11 09:44:55 +08:00
    如果是几千内的阶乘,确实查表会好些
    500
        12
    500  
       2023-01-11 09:58:26 +08:00
    http://www.luschny.de/math/factorial/FastFactorialFunctions.htm 介绍了 Split Recursive 的方式,
    虽然提供的是 C# 实现但没有涉及复杂语法,可以参考一下
    yangyuhan12138
        13
    yangyuhan12138  
    OP
       2023-01-11 10:24:49 +08:00
    @cccer 确实 正经人谁会这样写,但是因为这个是 我朋友公司 转正需要走做的考题...就是要用 plsql 写 ,主要看他的熟练程度 以及思维
    yangyuhan12138
        14
    yangyuhan12138  
    OP
       2023-01-11 10:26:23 +08:00
    @Alias4ck 当然试过了 结果是 2500 多位 我测试的结果 图片连接 s2.loli.net/2023/01/11/Ji1UHwWPerhBauQ.png 前边加 https:// number 不可能存的下
    yangyuhan12138
        15
    yangyuhan12138  
    OP
       2023-01-11 10:26:51 +08:00
    @Alias4ck 好像不用加
    Alias4ck
        16
    Alias4ck  
       2023-01-11 11:01:01 +08:00
    @yangyuhan12138 我记得 oracle 是可以反射调用 java 程序的 2500 位的话 你这种用数据库肯定做不了
    darklinden
        17
    darklinden  
       2023-01-11 17:39:58 +08:00
    大数计算的话,看下 js 的 bigint 实现?高低位运算然后使用数组存储?
    yangyuhan12138
        18
    yangyuhan12138  
    OP
       2023-01-12 11:17:12 +08:00
    思路是有的 但是公司要求用 Oracle 来解决,但是我不熟悉 Oracle 所以才来看看能不能直接捞到答案..
    yangyuhan12138
        19
    yangyuhan12138  
    OP
       2023-01-12 11:20:01 +08:00
    所以最后我还是自己实现了一下


    create or replace function multiply(num1 varchar2, num2 varchar2) return varchar2 as
    TYPE number_array IS VARRAY(4000) OF number;
    temp_array number_array;
    len1 number;
    len2 number;
    p1 number;
    p2 number;
    mul number;
    ss number;
    final_result varchar2(4000);
    begin
    temp_array := number_array();
    len1 := length(num1);
    len2 := length(num2);

    temp_array.extend(len1 + len2);
    FOR i IN 1..temp_array.count
    LOOP
    temp_array(i) := 0;
    END LOOP;
    -- Loop through the digits of the first number
    FOR i IN REVERSE 1..len1
    LOOP
    -- Loop through the digits of the second number
    FOR j IN REVERSE 1..len2
    LOOP
    mul := TO_NUMBER(SUBSTR(num1, i, 1)) * TO_NUMBER(SUBSTR(num2, j, 1));
    p1 := i + j - 1;
    p2 := i + j;
    ss := mul + temp_array(p2);
    temp_array(p1) := temp_array(p1) + floor(ss / 10);
    temp_array(p2) := mod(ss, 10);
    end loop;
    end loop;

    FOR i IN 1..temp_array.count
    LOOP
    if temp_array(i) = 0 and length(final_result) is null
    then
    continue ;
    end if;
    final_result := final_result|| temp_array(i);
    END LOOP;

    return final_result;
    end;

    create or replace function factorial(n number) return varchar2 as
    result varchar2(32767) := '1';
    begin
    for i in 1..n
    loop
    result := multiply(result, to_char(i));
    end loop;
    return result;
    end;

    select factorial(1000)
    from DUAL;
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5848 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 06:30 · PVG 14:30 · LAX 22:30 · JFK 01:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.