回 帖 发 新 帖 刷新版面

主题:超长数运算

很多人都会说到用数组来储存各位置上的数字,
而我觉得QB里的字符串特别是不定长字符串,
使用起来很方便,所以我很喜欢用QB的字符串函数
mid$(),instr()等等,方便快捷

不定长字符串最大可以去到32767个字符,
大概已经够用的了,还不够用的话,再定义一个字符数组
转换成十六进制来计算,每一个字符代替两位十六进制数字,够恐怖的了
我觉得我这辈子都不怎么会有这个机会用得上了,否则我该进天文学研究所去了.

DECLARE FUNCTION longx$ (a$, b$)  '乘法
DECLARE FUNCTION longqu$ (a$, b$) '除法
DECLARE FUNCTION longadd$ (a$, b$)'加法
DECLARE FUNCTION longsub$ (a$, b$)'减法
DECLARE FUNCTION cut0$ (a$)
DECLARE FUNCTION dao$ (a$)

FUNCTION cut0$ (a$)
c$ = a$
l% = LEN(c$)
DO UNTIL l% <= 1
   IF LEFT$(c$, 1) < "1" THEN
      l% = l% - 1
      c$ = RIGHT$(c$, l%)
   ELSE
      EXIT DO
   END IF
LOOP
cut0$ = c$
END FUNCTION

FUNCTION dao$ (a$)
b$ = a$
l% = LEN(b$)
FOR i% = 1 TO l% \ 2
  k$ = MID$(b$, i%, 1)
  MID$(b$, i%, 1) = MID$(b$, l% - i% + 1, 1)
  MID$(b$, l% - i% + 1, 1) = k$
NEXT
dao$ = b$
END FUNCTION

FUNCTION longadd$ (a$, b$)
a1$ = dao$(LTRIM$(RTRIM$(a$)))
b1$ = dao$(LTRIM$(RTRIM$(b$)))
la% = LEN(a1$)
lb% = LEN(b1$)
IF la% > lb% THEN l% = la% ELSE l% = lb%
FOR i% = 1 TO l%
    a% = VAL(MID$(a1$, i%, 1))
    b% = VAL(MID$(b1$, i%, 1))
    c% = a% + b% + k%
    k% = c% \ 10
    c$ = c$ + CHR$(48 + c%)
NEXT
IF k% > 0 THEN c$ = c$ + CHR$(48 + k%)
longadd$ = dao$(c$)
END FUNCTION

FUNCTION longqu$ (a$, b$)
a1$ = LTRIM$(RTRIM$(a$))
b1$ = LTRIM$(RTRIM$(b$))
la% = LEN(a1$)
lb% = LEN(b1$)
FOR i% = lb% TO la%
    c1$ = LEFT$(a1$, i%)
    k% = -1
    DO
      k% = k% + 1
      c2$ = c1$
      c1$ = longsub$(c1$, b1$)
    LOOP UNTIL LEFT$(c1$, 1) = "-"
    c$ = c$ + CHR$(48 + k%)
    c2$ = RTRIM$(LTRIM$(c2$))
    l2% = LEN(c2$)
    MID$(a1$, 1, i%) = SPACE$(i% - l2%) + c2$
NEXT
     'a1$为余数
longqu$ = cut0$(c$)
END FUNCTION

FUNCTION longsub$ (a$, b$)
a1$ = cut0$(LTRIM$(RTRIM$(a$)))
b1$ = cut0$(LTRIM$(RTRIM$(b$)))
la% = LEN(a1$)
lb% = LEN(b1$)
IF la% > lb% THEN l% = la% ELSE l% = lb%
IF la% < lb% OR (la% = lb% AND b1$ > a1$) THEN
   cc$ = "-"
   SWAP a1$, b1$
END IF
a1$ = dao$(a1$)
b1$ = dao$(b1$)
FOR i% = 1 TO l%
    a% = VAL(MID$(a1$, i%, 1))
    b% = VAL(MID$(b1$, i%, 1))
    c% = k% + a% - b%
    IF c% < 0 THEN
       c% = c% + 10
       k% = -1
    END IF
    c$ = c$ + CHR$(48 + c%)
NEXT
longsub$ = cc$ + cut0$(dao$(c$))
END FUNCTION

FUNCTION longx$ (a$, b$)
a1$ = dao$(LTRIM$(RTRIM$(a$)))
b1$ = dao$(LTRIM$(RTRIM$(b$)))
la% = LEN(a1$)
lb% = LEN(b1$)
c$ = SPACE$(la% + lb%)
FOR i% = 1 TO la%
   ia% = VAL(MID$(a1$, i%, 1))
  FOR j% = 1 TO lb%+1
   ib% = VAL(MID$(b1$, j%, 1))
   lc% = i% + j% - 1
   ic% = ia% * ib% + VAL(MID$(c$, lc%, 1)) + k%
   IF ic% > 9 THEN
      k% = ic% \ 10
      ic% = ic% MOD 10
   else
      k%=0
   END IF
   MID$(c$, lc%, 1) = CHR$(48 + ic%)
NEXT j%, i%
longx$ = dao$(RTRIM$(c$))
END FUNCTION

完全是按照日常口算方法去计算的,
暂时只做到整数的运算,小数点和符号的运算还没有加进来,
欢迎大家有时间帮忙提提意见如何加上小数点和符号的运算处理,
弄好后还可以加进括号的多项式计算.

回复列表 (共16个回复)

沙发

加精啊

板凳

我在doshome加精了

3 楼

这个方法好
用数组存一位数字太浪费了
就喜欢楼主这种不浪费的方法
呵呵,编程界也要响应“节约中国”的口号

4 楼

树组的话用long储存一个10000进制的数... 很销魂的...

5 楼

但是你的乘法不去0啊。。。
而且也没有取鱼(余)啊。。。

6 楼

10进制和10000进制都是一样的

OI竞赛的时候一般都是这样用的...

我的话用1个byte储存256进制的

7 楼

数组操作还需要一定的聚化操作
一个long四个字节,代替八位十六进制数
每个元素之间的聚合需要反复的转换计算

用字符串数组
一个字节两位十六进制数
和数组一样充分利用上了
而变得更灵活空间更辽阔.

8 楼

注意要控制字符在48-58内,头上可以是正副号,以后还可能用到小数点或E(XP),E(XP)后第一个也可以是正副号,否则。。。
在用户需要时才用E(XP)
第二版最好不要支持E(XP),支持小数/整数+ - * / \(整除) MOD(取余) ^(乘方) 前缀:long
第三版支持E(XP) 前缀:none(是功能扩展,不是增加)
第4版有DEC2HEX/DEC2OCT/DEC2BIN/HEX2DEC/OCT2DEC/BIN2DEC 前缀:ln
第5版有所有进制通用:AND/OR/XOR/EQV/IMP 前缀:long
到这里就不用了
第5版新增功能是最容易了

9 楼

16进制好
还可以储存地图数据,转换方便

10 楼

重新搞了一个乘法:

FUNCTION LongX$ (a$, b$)
  a$ = LTRIM$(RTRIM$(a$))
  b$ = LTRIM$(RTRIM$(b$))
  la = LEN(a$)
  lb = LEN(b$)
  lc = la + lb
  IF lc < 15 THEN
     xx1@ = VAL(a$)
     xx2@ = VAL(b$)
     LongX$ = LTRIM$(STR$(FIX(xx1@ * xx2@)))
     EXIT FUNCTION
  END IF
  s$ = " " + STRING$(lc - 1, 48)'SPACE$(lc)
  FOR i = ((la - 1) \ 13) * 13 + 1 TO 1 STEP -13
    a2@ = VAL(MID$(a$, i, 13))
    IF i + 12 > la THEN wa = la ELSE wa = i + 12
    z@ = 0
    FOR j = lb TO 1 STEP -1
      w = wa + j
      z@ = a2@ * VAL(MID$(b$, j, 1)) + VAL(MID$(s$, w, 1)) + z@
      z2@ = FIX(z@ / 10)
      MID$(s$, w, 1) = CHR$(48 + (z@ - z2@ * 10))
      z@ = z2@
    NEXT
    z@ = z@ + VAL(LEFT$(s$, w - 1))
    z3$ = LTRIM$(STR$(z@))
    MID$(s$, w - LEN(z3$)) = z3$
  NEXT i
  LongX$ = LTRIM$(s$)
END FUNCTION

我来回复

您尚未登录,请登录后再回复。点此登录或注册