现在的位置: 首页 > 综合 > 正文

powerbuilder Decimal内部表示方式解析

2017年12月08日 ⁄ 综合 ⁄ 共 4072字 ⁄ 字号 评论关闭

Decimal是16bytes数据类型。最大精度18位。

 

如果申明时写:dec var1 = xxx,它内部初始值会自动设置精度:

 

000014d9h: 01 00 08 00 F6 FF 09 00 00 00 00 00 00 00 B8 00 dec{8} q111111111111111111 = -0.0065535
000014d9h: 01 00 0C 00 60 79 9E 86 01 00 00 00 00 00 B8 00 dec{12} q111111111111111111 = -0.0065535
000014c9h: 01 00 00 00 FF FF 00 00 00 00 00 00 00 00 B8 00 dec q111111111111111111 = -65535
000014d9h: 01 00 01 00 FF FF 00 00 00 00 00 00 00 00 B8 00 dec q111111111111111111 = -6553.5
000014d9h: 01 00 02 00 FF FF 00 00 00 00 00 00 00 00 B8 00 dec q111111111111111111 = -655.35
000014d9h: 01 00 03 00 FF FF 00 00 00 00 00 00 00 00 B8 00 dec q111111111111111111 = -65.535
000014d9h: 01 00 04 00 FF FF 00 00 00 00 00 00 00 00 B8 00 dec q111111111111111111 = -6.5535
000014d9h: 01 00 05 00 FF FF 00 00 00 00 00 00 00 00 B8 00 dec q111111111111111111 = -0.65535
000014d9h: 01 00 06 00 FF FF 00 00 00 00 00 00 00 00 B8 00 dec q111111111111111111 = -0.065535
000014d9h: 01 00 07 00 FF FF 00 00 00 00 00 00 00 00 B8 00 dec q111111111111111111 = -0.0065535
000014d9h: 01 00 08 00 FF FF 00 00 00 00 00 00 00 00 B8 00 dec q111111111111111111 = -0.00065535

 

由上的hex可见,dec申明时系统决定精度,最大可能满足最好的保存方式。

而dec{8}的方式如果赋值长度超过,将被截取掉。

 

pbkiller有2个bug,一是没处理正负号,二是小于1的小数,它一直是保持小数点不动,也就是没处理指数(仅仅小于1的情况下,大于1的情况有处理ok)。

 

内部的二进制表示上看,低2位表示正负号,目前只使用了1bit,3-4位表示精度。4-12是以一个__int64表示的极大整数

 

为了解析这个decimal格式,整整花了一天时间。pb的real对应c++的float,double对应c++的double。

 

                iGetLen = 8;
                longlongValue=0;
                memcpy(&longlongValue,pDataResLocal + iDataOrPoint + 4,iGetLen);
                sReturn = IntToStr(longlongValue);

 

                //指数部分;如果申明dec var1,这个精度是根据赋值时自动进行的。
                //原则是尽可能保存完整。但是如果申明dec{8} var1,这精度是固定的。
                //给小数点
                inttemp = sReturn.Length();    //长度不要变动,后面给指数时还用到。
                if (inttemp >1){
                    sReturn = sReturn.SubString(1,1) + "." +
                               sReturn.SubString(2,inttemp - 1);
                }

 

                //去掉尾部的多余0
                intValue = inttemp + 1;  //小数点;
                while(intValue>3){
                    if(sReturn.SubString(intValue,1) == "0"){
                       intValue --;
                       if(intValue < 4) break;
                    }else{
                       break;
                    }
                }
                sReturn = sReturn.SubString(1,intValue);

                //变更指数
                iGetLen = 2;
                intValue = 0;
                memcpy(&intValue,pDataResLocal + iDataOrPoint + 2,iGetLen);
                if (intValue - inttemp + 1 !=0){
                    sReturn +="E" + IntToStr(-(intValue - inttemp + 1));
                }

                //处理正负号
                iGetLen = 1;
                intValue = 0;
                memcpy(&intValue,pDataResLocal + iDataOrPoint,iGetLen);

                if(intValue){
                    sReturn = "-" + sReturn;
                }

                break;

 

程序demo:

//
dec{8} q1 = -123.44320123
dec{8} q11 = 0.01
dec{8} q12 = 0.001
dec{8} q13 = 0.0001
dec{8} q14 = 0.00001
dec{8} q15 = 0.000001

dec{8} q16 = 3.14E-5
dec{8} q17 = 6500000000

dec{0} q2= 3.1415926514159265141592651415926514159265        //仅供测试系统的截取情况

dec{4} q3= 3.1415926514159265141592651415926514159265
dec{8} q4= 3.1415926514159265141592651415926514159265
dec{12} q5= 3.1415926514159265141592651415926514159265
dec{16} q6= 3.1415926514159265141592651415926514159265

dec{18} q7= 3.1415926514159265141592651415926514159265

any r1 = 3.1415926514159265141592651415926514159265

 

pbkiller结果:

decimal q1 = 123.44320123
decimal q11 = .1000000                          //here error
decimal q12 = .100000                            //here error  
decimal q13 = .10000                              //here error
decimal q14 = .1000                                //here error
decimal q15 = .100                                  //here error
decimal q16 = .3140                                //here error
decimal q17 = 6500000000.00000000
decimal q2 = 3
decimal q3 = 3.1416
decimal q4 = 3.14159265
decimal q5 = 3.141592651416
decimal q6 = 3.1415926514159265
decimal q7 = 3.141592651415926514
decimal r1 = 3.141592651415926514

 

我的decomplier:

global <FUNCTION_OR_SUBRUNTINE> <RETURN_DATATYPE> lf_111(<PARAM_LIST>) <THROWS_OBJNAME>
//Variables List
dec{8} q1 = -1.2344320123E2
dec{8} q11 = 1.0E-2
dec{8} q12 = 1.0E-3
dec{8} q13 = 1.0E-4
dec{8} q14 = 1.0E-5
dec{8} q15 = 1.0E-6
dec{8} q16 = 3.14E-5
dec{8} q17 = 6.5E9
dec{0} q2 = 3
dec{4} q3 = 3.1416
dec{8} q4 = 3.14159265
dec{12} q5 = 3.141592651416
dec{16} q6 = 3.1415926514159265
dec{18} q7 = 3.141592651415926514
dec r1 = 3.141592651415926514
还算满意。

 

 

 

抱歉!评论已关闭.