OldLiu 发表于 2019-2-24 09:31:42

[算法实战002]高精度正负浮点数四则运算

几年之前,论坛正搞笔记征集活动,才写了几篇,这个区就突然没了{:9_218:} ,就没怎么上论坛了
今天偶然看到汇编区回来了{:9_232:} ,发个帖子,
账号可能被注销了{:9_219:} ,emmm只能新搞一个了
https://attach.52pojie.cn/forum/201902/19/203337tv4hy08yom3oovmo.jpg
https://attach.52pojie.cn/forum/201902/19/203342tuxja8hjq1q8aaf8.jpg
;高精度正负浮点数四则运算 Algo
;Code By 老刘
;编译环境:MASM32 SDK
;编译指令:ml /coff 高精度正负浮点数四则运算.ASM /link /subsystem:console
;调用方法:
;        传参,参数1为数1对数2进行的运算(+、-、*、/),
;        参数2、3为分别为数1,数2参数。
;合规数字:1 01 1.0 00.100 -01.1234        (不和规数字:.1 3.)
;其他:
;        两个数字的最大长度为124位(包含负号、小数点、0)。
;        受MASM32 SDK中老旧的ArgClC函数限制,两个数字的总长度和应不超过188。
;        应尽量避免多余0的出现(如0100中开头的0、0.0010中最后的0),会削减除法运算的精度。
;参考:MHL批处理标准教程之高精度系列代码。


Include masm32rt.inc
Main Proto        ;主函数
_Addition Proto        ;加(减)法函数
_ArraySubtraction Proto        lpMinuend:dword,lpSubtrahend:dword,bArrayLength:byte        ;数组减法函数
_ArrayCompare Proto lpArray1:dword,lpArray2:dword,bArrayLength:byte        ;数组(表示的数字的)大小比较函数
_Multiplication Proto        ;乘法函数
_Division Proto        ;除法函数

.Data?
        szNum1 DB 128 Dup (?)
        szNum2 DB 128 Dup (?)
        bNum1Symbol DB ?
        bNum2Symbol DB ?
        bNum1Length DB ?
        bNum2Length DB ?
        bNum1IntegralPartLength DB ?
        bNum1DecimalPartLength DB ?
        bNum2IntegralPartLength DB ?
        bNum2DecimalPartLength DB ?
        bNum1LengthPlusNum2Length DB ?
        bNum1IntegralPartLengthPlusNum2IntegralPartLength DB ?
        bNum1DecimalPartLengthPlusNum2DecimalPartLength DB ?
        bNum1LengthPlusNum2DecimalPartLength DB ?
        bNum2LengthPlusNum1DecimalPartLength DB ?
        lpNum1IntegralPart DD ?
        lpNum1DecimalPart DD ?
        lpNum2IntegralPart DD ?
        lpNum2DecimalPart DD ?
;End Data?

.Code
        Main Proc
                Local @szOperation:word        ;运算符+null的长度
               
                ;获得参数并赋值变量
                Invoke ArgClC,1,Addr @szOperation
                Invoke ArgClC,2,Addr szNum1
                Invoke ArgClC,3,Addr szNum2
               
                Lea Eax,szNum2
                Mov lpNum2IntegralPart,Eax        ;初步确定指针
                Lea Esi,szNum1
                Mov lpNum1IntegralPart,Esi
               
                ;正负号判断(0正1负)
                LodSB        ;Esi=lpNum1IntegralPart
                .If Al == '-'
                        Mov bNum1Symbol,1
                        Inc lpNum1IntegralPart        ;指针修正,使其指向数字
                .Else
                        Mov bNum1Symbol,0
                .EndIf
                Mov Ax,@szOperation
                Mov Ah,Al
                Mov Esi,lpNum2IntegralPart
                LodSB
                .If Ah == '-'        ;负负得正的处理
                        .If Al == '-'
                                Mov bNum2Symbol,0
                                Inc lpNum2IntegralPart
                        .Else
                                Mov bNum2Symbol,1
                        .EndIf
                .Else
                        .If Al == '-'
                                Mov bNum2Symbol,1
                                Inc lpNum2IntegralPart
                        .Else
                                Mov bNum2Symbol,0
                        .EndIf
                .EndIf
               
                ;获得两数的小数、整数部分长度;
                ;获得两数的小数部分的内存地址;
                ;去掉小数点;将数字从Ascii转为Byte。
                Mov bNum1IntegralPartLength,0
                Mov bNum1DecimalPartLength,0
                Mov bNum2IntegralPartLength,0
                Mov bNum2DecimalPartLength,0
                Mov Esi,lpNum1IntegralPart
                Mov Edi,Esi        ;同时操作一个字符串
                Lea Ebx,bNum1IntegralPartLength
                Lea Ecx,bNum1DecimalPartLength
                Xor Edx,Edx        ;作为循环flag
                @@:
                LodSB
                .While Al != '.' && Al != NULL
                        Inc Byte Ptr
                        Sub Al,30H        ;将数字从Ascii转为Byte
                        StoSB        ;重新写回去
                        LodSB
                .EndW
                Push Esi
                .If Al != NULL
                        LodSB
                        .While Al != NULL
                                Inc Byte Ptr
                                Sub Al,30H
                                StoSB
                                LodSB
                        .EndW
                .EndIf
                .If Edx == 0
                        Pop lpNum1DecimalPart
                        Mov Esi,lpNum2IntegralPart
                        Mov Edi,Esi
                        Lea Ebx,bNum2IntegralPartLength
                        Lea Ecx,bNum2DecimalPartLength
                        Inc Edx
                        Jmp @B
                .EndIf
                Pop lpNum2DecimalPart
                Dec lpNum1DecimalPart        ;去掉了小数点后的指针修正
                Dec lpNum2DecimalPart
               
                ;计算各种长度。
                Mov Al,bNum1IntegralPartLength
                Add Al,bNum1DecimalPartLength
                Mov bNum1Length,Al
                Add Al,bNum2DecimalPartLength
                Mov bNum1LengthPlusNum2DecimalPartLength,Al
                Add Al,bNum2IntegralPartLength
                Mov bNum1LengthPlusNum2Length,Al
                Sub Al,bNum1IntegralPartLength
                Mov bNum2LengthPlusNum1DecimalPartLength,Al
                Sub Al,bNum1DecimalPartLength
                Mov bNum2Length,Al
                Sub Al,bNum2DecimalPartLength
                Add Al,bNum1IntegralPartLength
                Mov bNum1IntegralPartLengthPlusNum2IntegralPartLength,Al
                Sub Al,bNum1LengthPlusNum2Length
                Mov Al,bNum1LengthPlusNum2Length
                Sub Al,bNum1IntegralPartLengthPlusNum2IntegralPartLength
                Mov bNum1DecimalPartLengthPlusNum2DecimalPartLength,Al
               
                ;调用相应的计算函数。
                Mov Ax,@szOperation
                .If Al == '+' || Al == '-'
                        Call _Addition
                .ElseIf Al == '*'
                        Call _Multiplication
                .ElseIf Al == '/'
                        Call _Division
                .EndIf
               
                Ret
        Main EndP
       
        _Addition Proc
                Local @bNum1Array:byte,@bNum2Array:byte        ;其中之一同时作为结果数组
                Local @bDestSymbol:byte,@lpDestArray
                Local @bDestEqualZeroSign:byte,@bDestDecimalPartEqualZeroSign:byte
                Local @bDestDecimalPartLength:byte,@szDest:byte
                Mov Al,bNum1DecimalPartLengthPlusNum2DecimalPartLength        ;初步确定结果小数部分长度
                Mov @bDestDecimalPartLength,Al
               
                ;数组清0。
                Xor Eax,Eax
                Mov Ecx,SizeOf @bNum1Array
                Lea Edi,@bNum1Array
                Rep StoSB
                Mov Ecx,SizeOf @bNum2Array
                Lea Edi,@bNum2Array
                Rep StoSB
               
                ;数1存入数组。
                Mov Esi,lpNum1IntegralPart
                Lea Edi,@bNum1Array
                Movzx Eax,bNum1LengthPlusNum2DecimalPartLength
                Add Edi,Eax
                Dec Edi ;数组从0开始
                Movzx Ecx,bNum1Length
                .Repeat
                        MovSB
                        Dec Edi        ;倒序装入数组
                        Dec Edi
                .UntilCxZ
               
                ;数2存入数组。
                Mov Esi,lpNum2IntegralPart
                Lea Edi,@bNum2Array
                Movzx Eax,bNum2LengthPlusNum1DecimalPartLength
                Add Edi,Eax
                Dec Edi
                Movzx Ecx,bNum2Length
                .Repeat
                        MovSB
                        Dec Edi
                        Dec Edi
                .UntilCxZ
               
                ;判断同异号并计算结果。
                Mov @bDestEqualZeroSign,0FFH
                Mov Al,bNum1Symbol
                Xor Al,bNum2Symbol
                .If Al == 0        ;同号
                        ;获取结果符号。
                        Mov Al,bNum1Symbol
                        Mov @bDestSymbol,Al
                       
                        ;计算结果。
                        Xor Eax,Eax        ;Ah进位清0
                        Lea Esi,@bNum2Array
                        Lea Edi,@bNum1Array        ;作为结果数组
                        Mov @lpDestArray,Edi
                        Movzx Ecx,bNum1LengthPlusNum2Length        ;计数器
                        Mov Bl,10        ;十进制
                        .Repeat
                                LodSB
                                Add Al,
                                Add Al,Ah
                                Cbw
                                Div Bl
                                Xchg Al,Ah
                                StoSB
                        .UntilCxZ
                .Else        ;异号
                        ;比较两数大小并获取结果符号。
                        Invoke _ArrayCompare,Addr @bNum1Array,Addr @bNum2Array,bNum1LengthPlusNum2Length
                        .If Eax == 1        ;(绝对值)数1>数2
                                Mov Al,bNum1Symbol
                                Mov @bDestSymbol,Al
                                Lea Edi,@bNum1Array        ;作为结果数组
                                Mov @lpDestArray,Edi
                                Invoke _ArraySubtraction,Edi,Addr @bNum2Array,bNum1LengthPlusNum2Length
                        .ElseIf Eax == 2
                                Mov Al,bNum2Symbol
                                Mov @bDestSymbol,Al
                                Lea Edi,@bNum2Array
                                Mov @lpDestArray,Edi
                                Invoke _ArraySubtraction,Edi,Addr @bNum1Array,bNum1LengthPlusNum2Length
                        .Else        ;两数相等
                                Inc @bDestEqualZeroSign        ;=0
                        .EndIf
                .EndIf
               
                ;验证加法结果是否为0。
                ;(其实就是应对0+0或-0-0这样的情况)
                Mov Al,@bDestEqualZeroSign
                .If Al == 0FFH
                        Mov Esi,@lpDestArray
                        Movzx Ecx,bNum1LengthPlusNum2Length
                        .Repeat
                                LodSB
                        .UntilCxZ Al != 0
                        .If Al == 0        ;全部跑完,且值为0
                                Inc @bDestEqualZeroSign
                        .EndIf
                .EndIf
               
                ;结果转为字符串。
                Mov Al,@bDestEqualZeroSign
                .If Al == 0FFH        ;值为FF在此表示值不为0
                        Mov Al,@bDestDecimalPartLength
                        .If Al != 0        ;两整数相加时小数部分肯定为0
                                ;修正结果小数部分长度。
                                Mov Esi,@lpDestArray
                                Movzx Ecx,@bDestDecimalPartLength
                                .Repeat
                                        LodSB
                                .UntilCxZ Al != 0
                                .If Al != 0        ;小数部分不为0
                                        Inc Cl        ;长度从1开始
                                        Mov @bDestDecimalPartLength,Cl
                                .Else
                                        Mov @bDestDecimalPartLength,Al        ;=0
                                .EndIf
                        .EndIf
                       
                        ;结果字符串写入。
                        Lea Edi,@szDest
                        ;结果符号判断&写入。
                        Mov Al,@bDestSymbol
                        .If Al == 1        ;结果为负
                                Mov Al,'-'
                                StoSB
                        .EndIf
                        ;结果的整数部分转为字符串。
                        Movzx Esi,bNum1LengthPlusNum2Length
                        Add Esi,@lpDestArray
                        Dec Esi
                        Movzx Ecx,bNum1IntegralPartLengthPlusNum2IntegralPartLength
                        .Repeat        ;去除先导0
                                LodSB
                                Dec Esi
                                Dec Esi
                        .UntilCxZ Al !=0
                        Add Al,30H        ;Byte转Ascii
                        StoSB        ;整数部分的最高位或0写入
                        .While Ecx != 0        ;剩余整数部分写入
                                LodSB
                                Dec Esi
                                Dec Esi
                                Add Al,30H
                                StoSB
                                Dec Ecx
                        .EndW
                        ;结果小数点及小数部分转为字符串。
                        Movzx Ecx,@bDestDecimalPartLength        ;计数器
                        .If Cl != 0
                                Mov Al,'.'
                                StoSB        ;小数点写入
                                .Repeat
                                        LodSB
                                        Dec Esi
                                        Dec Esi
                                        Add Al,30H
                                        StoSB
                                .UntilCxZ
                        .EndIf
                        Mov DWord Ptr ,000A0DH        ;字符串结尾
                .Else
                        ;结果字符串写入
                        Lea Edi,@szDest
                        Mov DWord Ptr ,000A0D30H        ;"0\r\n"+null
                .EndIf
               
                ;输出结果。
                Invoke StdOut,Addr @szDest
               
                Xor Eax,Eax
                Ret
        _Addition EndP
       
        _ArraySubtraction Proc Uses Eax Ebx Ecx Esi Edi lpMinuend:dword,lpSubtrahend:dword,bArrayLength:byte
                ;参数:被减数数组指针、减数数组指针、两个数组的共同长度。
                ;要求:被减数大于减数。
               
                Mov Edi,lpMinuend
                Mov Esi,lpSubtrahend
                Movzx Ecx,bArrayLength
                Xor Ebx,Ebx        ;Bl借位清0
                .Repeat
                        Mov Al,
                        Sub Al,Bl
                        Sub Al,
                        .If Sign?        ;结果为负
                                Add Al,10
                                Mov Bl,1
                        .Else
                                Xor Ebx,Ebx
                        .EndIf
                        StoSB
                        Inc Esi
                .UntilCxZ
               
                Ret
        _ArraySubtraction EndP
       
        _ArrayCompare Proc Uses Edi Esi Ecx lpArray1:dword,lpArray2:dword,bArrayLength:byte
                ;参数:数组1、数组2、两个数组的共同长度。
                ;返回值(存于Eax中):0-两数(组)相等;1-数1大于数2;2-数2大于数1。
               
                Mov Edi,lpArray1
                Mov Esi,lpArray2
                Movzx Ecx,bArrayLength        ;计数器
                Add Esi,Ecx
                Dec Esi        ;指向数组最后一个元素
                Add Edi,Ecx
                Dec Edi
               
                .Repeat
                        Xchg Esi,Edi
                        LodSB        ;数1
                        Dec Esi
                        Dec Esi
                        Mov Ah,Al
                        Xchg Esi,Edi
                        LodSB        ;数2
                        Dec Esi
                        Dec Esi
                        .If Ah > Al        ;(绝对值)数1>数2
                                Mov Eax,1
                                Ret
                        .ElseIf Ah < Al
                                Mov Eax,2
                                Ret
                        .EndIf
                .UntilCxZ
                Xor Eax,Eax        ;能运行到这里,说明两数相等。
               
                Ret
        _ArrayCompare EndP
       
        _Multiplication Proc
                Local @bDestArray:byte,@bDestDecimalPartLength:byte,@szDest:byte
                Local @bDestEqualZeroSign:byte,@bDestSymbol:byte
               
                ;结果数组清0。
                Xor Eax,Eax
                Mov Ecx,SizeOf @bDestArray
                Lea Edi,@bDestArray
                Rep StoSB
               
                ;数1、数2从低到高按位相乘并放入结果数组。
                Lea Edi,@bDestArray
                Mov Ebx,lpNum1IntegralPart
                Movzx Edx,bNum1Length
                Add Ebx,Edx
                Dec Ebx        ;指针修正
                Xchg Dh,Dl        ;Dh做计数器
                ;使用数1的每一位乘数2的全部位。
                .While Dh != 0
                        Mov Dl,        ;Dl做因数
                        Push Edi
                       
                        ;数2初始化。
                        Mov Esi,lpNum2IntegralPart
                        Movzx Ecx,bNum2Length        ;Ecx做计数器
                        Add Esi,Ecx
                        Dec Esi
                        .Repeat
                                LodSB
                                Dec Esi        ;逆读取指针修正;数2换高一位
                                Dec Esi
                                Mul Dl
                                Add ,Al
                                Inc Edi
                        .UntilCxZ
                       
                        ;进位处理,避免溢出。
                        Movzx Ecx,bNum2Length        ;要处理进位的长度=数2的长度
                        Mov Edi,        ;使Edi指向需进位处理的首个数字
                        Mov Dl,10
                        .Repeat
                                Movzx Ax,Byte Ptr
                                Div Dl
                                Mov ,Ah
                                Add ,Al
                                Inc Edi
                        .UntilCxZ
                       
                        ;根据乘法法则,数1换高一位,结果也换高一位。
                        Pop Edi
                        Dec Ebx
                        Inc Edi
                       
                        Dec Dh
                .EndW
               
                ;判断结果是否为0;
                ;获得结果符号。
                Movzx Ecx,bNum1DecimalPartLength
                Add Cl,bNum2DecimalPartLength
                Mov @bDestEqualZeroSign,0
                Lea Esi,@bDestArray
                .If Cl > 0
                        .Repeat
                                LodSB
                        .UntilCxZ Al != 0
                        .If Al != 0        ;小数部分非0
                                ;小数部分非0说明乘积不为0,获得结果符号。
                                Mov Al,bNum1Symbol
                                Xor Al,bNum2Symbol
                                Mov @bDestSymbol,Al
                               
                                Inc Ecx
                                Mov @bDestDecimalPartLength,Cl
                        .Else
                                Mov @bDestDecimalPartLength,0
                                ;判断整数部分是否为0。
                                Movzx Ecx,bNum1IntegralPartLength
                                Add Cl,bNum2IntegralPartLength
                                .Repeat
                                        LodSB
                                .UntilCxZ Al != 0
                                .If Al == 0        ;乘积为0,不管正负,使结果为正(避免输出-0)
                                        Mov @bDestSymbol,0
                                        Inc @bDestEqualZeroSign        ;=1
                                .EndIf
                        .EndIf
                .Else        ;结果不存在小数部分
                        Mov @bDestDecimalPartLength,0
                .EndIf
               
                ;生成结果字符串。
                Lea Esi,@bDestArray
                Movzx Ecx,bNum1Length
                Add Cl,bNum2Length
                Add Esi,Ecx        ;使得Esi指向数组末尾
                Lea Edi,@szDest
                .If @bDestEqualZeroSign == 1
                        Mov DWord Ptr ,000A0D30H        ;"0\r\n"+null
                .Else
                        ;获得整数部分长度。
                        Movzx Ecx,bNum1IntegralPartLength
                        Add Cl,bNum2IntegralPartLength
                       
                        ;写入符号。
                        .If @bDestSymbol == 1
                                Mov Al,'-'
                                StoSB
                        .EndIf
                       
                        ;略过整数部分开头的0。
                        .Repeat
                                Dec Esi
                                LodSB
                                Dec Esi
                        .UntilCxZ Al != 0
                        Inc Ecx
                       
                        ;写入整数部分。
                        .Repeat
                                LodSB
                                Dec Esi
                                Dec Esi
                                Add Al,30H        ;Byte转Ascii
                                StoSB
                        .UntilCxZ
                       
                        ;写入小数部分(如果有)。
                        Movzx Ecx,@bDestDecimalPartLength
                        .If Cl > 0
                                ;写入小数点。
                                Mov Al,'.'
                                StoSB
                                ;写入小数部分。
                                .Repeat
                                        LodSB
                                        Dec Esi
                                        Dec Esi
                                        Add Al,30H
                                        StoSB
                                .UntilCxZ
                        .EndIf
                       
                        ;字符串结尾。
                        Mov DWord Ptr ,000A0DH
                .EndIf
               
                ;输出结果。
                Invoke StdOut,Addr @szDest
               
                Xor Eax,Eax
                Ret
        _Multiplication EndP
       
        _Division Proc
                Local @szDest:byte,@bDividendArray:byte,@bDivisorArray:byte,@lpDest
                Local @bDestDecimalPointPos:byte,@bDivisorArrayLength:byte
                Local @bDestEqualZeroSign:byte,@bDestIntegralPartEqualZeroSign:byte,@bDecimalPointWriteInSign:byte
               
                ;将除数的有效数字存入除数数组。
                Mov Esi,lpNum2IntegralPart
                Movzx Ecx,bNum2IntegralPartLength
                .Repeat        ;去除整数部分多余的0
                        LodSB
                .UntilCxZ Al != 0
                .If Al != 0
                        Inc Ecx
                        Mov bNum2IntegralPartLength,Cl
                        Dec Esi        ;指向有效数字
                        Add Cl,bNum2DecimalPartLength
                .Else        ;整数部分均为0,继续去0直到遇到有效数字
                        Mov bNum2IntegralPartLength,0
                        Movzx Ecx,bNum2DecimalPartLength
                        .If Ecx != 0        ;除数存在小数部分
                                .Repeat
                                        LodSB
                                .UntilCxZ Al != 0
                                .If Al != 0
                                        Inc Ecx
                                        Dec Esi        ;指向有效数字
                                .Else        ;除数为0
                                        Mov Eax,1
                                        Ret
                                .EndIf
                        .Else        ;不存在小数部分,除数为0
                                Mov Eax,1
                                Ret
                        .EndIf
                .EndIf
                ;按位(倒序)存入除数数组。
                Mov @bDivisorArrayLength,Cl        ;有效数字到除数末尾的长度
                Lea Edi,@bDivisorArray
                Add Edi,Ecx
                Dec Edi        ;指向数组最后一个元素
                .Repeat
                        LodSB
                        StoSB
                        Dec Edi
                        Dec Edi
                .UntilCxZ
                ;为配合运算,将除数数组增加一个元素;
                ;不影响除数数组代表的除数的大小。
                Movzx Ecx,@bDivisorArrayLength
                Inc @bDivisorArrayLength
                Lea Eax,@bDivisorArray        ;此时Eax+Ecx指向新增的元素
                Mov Byte Ptr ,0        ;清0
               
                ;计算结果小数点的位置。
                Mov Al,bNum1IntegralPartLength
                Add Al,bNum2DecimalPartLength
                Mov @bDestDecimalPointPos,Al
               
                ;判断被除数是否为0;
                ;判断结果符号并写入。
                Mov Esi,lpNum1IntegralPart
                Movzx Ecx,bNum1Length
                .Repeat
                        LodSB
                .UntilCxZ Al != 0
                .If Al == 0
                        Mov @bDestEqualZeroSign,1
                        Lea Eax,@szDest
                        Mov DWord Ptr ,000A0D30H        ;"0\r\n"+null
                .Else
                        Mov @bDestEqualZeroSign,0
                        Mov Al,bNum1Symbol
                        Xor Al,bNum2Symbol
                        .If Al == 0        ;结果为正
                                Lea Eax,@szDest
                                Mov @lpDest,Eax
                        .Else        ;结果为负
                                Lea Eax,@szDest
                                Mov Byte Ptr ,'-'
                                Inc Eax
                                Mov @lpDest,Eax
                        .EndIf
                .EndIf
               
                ;被除数数组清空。
                Xor Eax,Eax
                Mov Ecx,SizeOf @bDividendArray
                Lea Edi,@bDividendArray
                Rep StoSB
               
                ;进行除法运算并生成最终字符串。
                .If @bDestEqualZeroSign != 1
                        ;获得被除数数组起始元素地址;
                        Lea Esi,@bDividendArray
                        Mov Ebx,SizeOf @bDividendArray
                        Dec Ebx        ;此时Esi+Ebx指向被除数数组末尾
                        Sub Bl,@bDivisorArrayLength        ;作为计算终止的标识之一
                        Add Esi,Ebx        ;此时Esi指向(当前的)被除数数组起始元素地址
                        Mov Bh,bNum1Length
                        Mov Ecx,lpNum1IntegralPart        ;作为被除数的读取指针
                        Sub Bl,4        ;减小精度,为字符串中数字以外的其它字符保留空间
                        Mov Edi,@lpDest        ;Edi作为字符串指针
                        Mov Dh,@bDestDecimalPointPos        ;Dh作为小数点写入的标识
                        Mov @bDestIntegralPartEqualZeroSign,0
                       
                        ;开始除法(减法模拟)运算。
                        .While Bl > 0
                                Invoke _ArrayCompare,Esi,Addr @bDivisorArray,@bDivisorArrayLength
                                Dec Bl
                                .If Eax <= 1        ;被除数数组>=除数数组,做减法
                                        Xor Dl,Dl        ;Dl作为商
                                        .While Eax != 2
                                                Invoke _ArraySubtraction,Esi,Addr @bDivisorArray,@bDivisorArrayLength
                                                Invoke _ArrayCompare,Esi,Addr @bDivisorArray,@bDivisorArrayLength
                                                Inc Dl
                                        .EndW
                                        Mov Al,Dl
                                        Add Al,30H
                                        StoSB
                                        Mov @bDestIntegralPartEqualZeroSign,1
                                .Else        ;被除数数组已经(被减到)小于除数数组
                                        ;用被除数将被除数数组添加一位。
                                        Dec Esi
                                        .If Bh > 0        ;被除数未全部放入数组
                                                Mov Al,Byte Ptr
                                                Mov Byte Ptr ,Al
                                                Inc Ecx
                                                Dec Bh
                                        .EndIf
                                        ;若被除数全部放入数组,则只需添0,由于数组已经清空,无需处理。
                                       
                                        ;判断是否需要向字符串中写入小数点。
                                        .If Dh == 0 && @bDecimalPointWriteInSign == 0
                                                Mov @bDecimalPointWriteInSign,1
                                                .If @bDestIntegralPartEqualZeroSign == 0
                                                        Mov @bDestIntegralPartEqualZeroSign,1
                                                        Mov Al,'0'
                                                        StoSB
                                                .EndIf
                                                Mov Al,'.'
                                                StoSB
                                        .EndIf
                                        Dec Dh
                                       
                                        ;判断是否处理完成;
                                        ;写入0。
                                        Invoke _ArrayCompare,Esi,Addr @bDivisorArray,@bDivisorArrayLength
                                        .If Eax == 2
                                                .If Bh == 0 && @bDecimalPointWriteInSign == 1        ;被除数非零数全部放入数组且被除数整数部分除完
                                                        Movzx Ecx,@bDivisorArrayLength        ;判断被除数数组是否除完(全空)
                                                        .Repeat
                                                                Lea Eax,
                                                                Mov Al,Byte Ptr
                                                        .UntilCxZ Al != 0
                                                        .If Al == 0
                                                                .If Dh == 0FFH        ;小数点刚写入,已经计算完成
                                                                        Dec Edi        ;去掉小数点
                                                                .EndIf
                                                                .Break
                                                        .EndIf
                                                .EndIf
                                                .If @bDestIntegralPartEqualZeroSign == 1
                                                        Mov Al,'0'
                                                        StoSB
                                                .EndIf
                                        .EndIf
                                .EndIf
                        .EndW
                .EndIf
                Mov DWord Ptr ,00000A0DH        ;字符串结尾
               
                ;输出结果。
                Invoke StdOut,Addr @szDest
               
                Xor Eax,Eax
                Ret
        _Division EndP
       
        Start:
                Call Main
                Invoke ExitProcess,Eax
        End Start
End
页: [1]
查看完整版本: [算法实战002]高精度正负浮点数四则运算