// // FLOATMATH-R.VDM Ch. Ziemski 03.01.2003 // 11.01.2003 // // IN: T-Reg 103: simple math formula like 1.2345 / 9.87 // Num-Reg 103: additional precision used for division (max. 8) // It tries to do some rounding. // OUT: T-Reg 103: Result // // // Attention: No error handling yet! ONLY FOR TESTING, NOT FOR PRODUCTIVE ENVIRONMENT! // // //----------------------------------------------------- // // value 1 // #81 # of decimals // #82 as number, without decimal point // $82 as string, " // // value 2 // #91 # of decimals // #92 as number, without decimal point // $92 as string, " // // #93 temp for Reg_Size // // #94 Max # of decimals // #95 digits for precision // // #96 function // #97 buffer# // #98 temp // #99 temp // $99 temp // //---------------------------------------------------------------- #97=Buf_Num Buf_Switch(Buf_Free) #95=Min(#103, 8) // max. precision of 8 digits (one of the 9 is for rounding purposes) Reg_Ins(103) // T-Reg 103 contains the simple math term BoF #103=81 Call("GET_NUMBER") // get first number Match("|[|W]", ADVANCE) if(Match("|{+,-,*,/}", ADVANCE) != 0){ // get function return // error } #96=Match_Item() #103=91 Call("GET_NUMBER") // get second number if(#96 < 3 ){ // add/subtract Call("EXPAND_SMALLER") // #94 then contains # of digits to "remove" later if(#96 == 1 ){ // add #106 = #82 + #92 }else{ // subtr #106 = #82 - #92 } }else{ if(#96 == 3 ){ // multpl #106 = #82 * #92 #94 = #81 + #91 // sum of decimals for later removal }else{ // division Call("EXPAND_SMALLER") // #94 then contains # of digits to "remove" later #106 = #82 / #92 // the integer part #99 = #82 % #92 // remainder Num_Str(#99, 99, LEFT+NOCR) #93 = Reg_Size(99) for(#105=#93 ; #105<=10 ; #105++){ // expand the remainder with 0's as far as possible if(Reg_Size(99) == 9){ #99 = Num_Eval_Reg(99) // check limits if(#99 < (MAXNUM/10)){ Reg_Set(99, "0", APPEND) } break } Reg_Set(99, "0", APPEND) } #99 = Num_Eval_Reg(99) // convert to number #99 = #99 / #92 // calculate the decimal part with maximal possible precision Buf_Empty(OK) Num_Ins(#99, LEFT+NOCR) Ins_Text("0000000000") Reg_Copy_Block(99, 0, #95+1) // get it back with desired precision + 1 #99 = Num_Eval_Reg(99) // convert to number #99 = (#99 + 5) / 10 // for rounding } } // insert decimal point at pos #94 (and possible insertion of leading 0's) Buf_Empty(OK) Num_Ins(#106, LEFT+NOCR) EoL if(#96 == 4 ){ // division Ins_Text(".") Num_Ins(#99, LEFT+NOCR) }else{ if(#94 < Cur_Pos){ Char(-#94) Ins_Text(".") }else{ #94=#94-Cur_Pos BoF Ins_Text("0.") for(#105=1; #105<=#94 ; #105++){ Ins_Text("0") } } } Reg_Copy_Block(103, 0, EoL_Pos) // save result in T-Reg 103 Buf_Quit(OK) Buf_Switch(#97) return // ============================================================= :GET_NUMBER: // in: #103 = base register Match("|[|W]", ADVANCE) if(Match("-")==0){ Char(1) #106=-1 }else{ #106=1 } #104=Cur_Pos Match("|{|D,.}", ALL+ADVANCE) #105=Cur_Pos Search_Block(".", #104,#105, BEGIN+NOERR) if(!EM){ #@103 = #105 - Cur_Pos - 1 Del_Char(1) #105-- }else{ #@103=0 } #103++ Goto_Pos(#104) #@103=Num_Eval(SUPPRESS+ADVANCE) Reg_Copy_Block(#103, #104, #105) if(#106 == -1){ // set the sign #@103 *= -1 Reg_Set(#103, "-", INSERT) } return //========================= :EXPAND_SMALLER: #94 = Max(#81,#91) if(#81 != #91){ // if different number of decimals if(#81 < #91){ #104=82 }else{ #104=92 } #98 = #94 - Min(#81,#91) for(#105=1 ; #105<=#98 ; #105++){ // expand the appropr. register with 0's Reg_Set(#104, "0", APPEND) } #@104 = Num_Eval_Reg(#104) // convert to number } return //=================================================================================