• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-162  評論-223  文章-30  trackbacks-0
            存儲格式
               Oracle Number數據類型是變長的,占0~22字節,不像編程語言中的2/4字節整數或4/8字節浮點數,關于它的存儲格式與解析,DSI上有詳細的描述,如下所示
                         
               
               符號位/指數字節描述如下
                        
               
               數字字節描述如下
                        
               
               正數或零值的計算
                        
               
               負數值的計算
                        

            解析實現
               由于Oracle Number的精度高達38位,遠超出了基本定長整數或浮點數表達的數值范圍,因此解析實際上是大整數/實數的四則運算,為避免造輪子,本文使用了GMP開源庫(https://gmplib.org/),用于任意精度的算術運算,操作有符號整數、有理數和浮點數,除了在GMP機器上運行的可用內存所暗示的精度之外,對精度沒有實際的限制。解析實現的核心函數是orcl_raw2number
             1 #include <stdio.h>
             2 #include <assert.h>
             3 #include <gmp.h>
             4 
             5 #define MAX_PREC  256
             6 
             7 static mpf_t s_base100;
             8 static mpf_t s_one;
             9 
            10 static void init_mpf_globals()
            11 {
            12     mpf_init_set_ui(s_base100, 100);
            13     mpf_init_set_ui(s_one, 1);
            14 }
            15 
            16 static void clear_mpf_globals()
            17 {
            18     mpf_clear(s_base100);
            19     mpf_clear(s_one);
            20 }
            21 
            22 static void orcl_raw2number(unsigned char *data, unsigned int len, mpf_t result)
            23 {
            24     unsigned int sign = *data, digit, i;
            25     int exp = sign>=128 ? sign-193 : 62-sign;
            26     int exp_val;
            27     mpf_t tmp;
            28 
            29     mpf_init2(tmp, MAX_PREC);
            30     mpf_init2(result, MAX_PREC);
            31 
            32     if(sign & 0x80){
            33         for(i=1; i<len; ++i){
            34             digit = data[i] - 1;
            35             assert(0<=digit && digit<=99);
            36 
            37             exp_val = exp - i + 1;
            38             if(exp_val < 0){ 
            39                 mpf_pow_ui(tmp, s_base100, -exp_val);
            40                 mpf_div(tmp, s_one, tmp);    
            41             }else
            42                 mpf_pow_ui(tmp, s_base100, exp_val);
            43                                 
            44             mpf_mul_ui(tmp, tmp, digit);
            45             mpf_add(result, result, tmp);
            46         }
            47     
            48     }else{
            49         --len; //ignore the last byte
            50         for(i=1; i<len; ++i){
            51             digit = 101 - data[i];
            52             assert(0<=digit && digit<=99);
            53 
            54             exp_val = exp - i + 1;
            55             if(exp_val < 0){ 
            56                 mpf_pow_ui(tmp, s_base100, -exp_val);
            57                 mpf_div(tmp, s_one, tmp);    
            58             }else
            59                 mpf_pow_ui(tmp, s_base100, exp_val);
            60                                 
            61             mpf_mul_ui(tmp, tmp, digit);
            62             mpf_add(result, result, tmp);
            63         }
            64 
            65         mpf_neg(result, result);
            66     }
            67     
            68     mpf_clear(tmp);
            69 }

            測試用例
               測試了123456.789、-123456.789、Oracle Number實際最大最小值、Oracle Number理論最大最小值
             1 int main(int argc, char *argv[])
             2 {
             3     int n = 19;
             4     char buf[256];
             5     mpf_t r;
             6 
             7     init_mpf_globals();
             8 
             9     //123456.789
            10     unsigned char data[] = {0xc3,0xd,0x23,0x39,0x4f,0x5b};    
            11     orcl_raw2number(data, sizeof(data), r);
            12     gmp_snprintf(buf, sizeof(buf), "%Ff\n\t%.*Ff(%d digits)", r, n, r, n);
            13     printf("result: %s\n", buf);
            14     printf("\t"); mpf_out_str(NULL, 10, 0, r); printf("\n");
            15     mpf_clear(r);
            16 
            17     //-123456.789
            18     unsigned char data2[] = {0x3c,0x59,0x43,0x2d,0x17,0xb,0x66};
            19     orcl_raw2number(data2, sizeof(data2), r);
            20     gmp_snprintf(buf, sizeof(buf), "%Ff\n\t%.*Ff(%d digits)", r, n, r, n);
            21     printf("result: %s\n", buf);
            22     printf("\t"); mpf_out_str(NULL, 10, 0, r); printf("\n");
            23     mpf_clear(r);
            24 
            25     //0
            26     unsigned char zero[] = {0x80};
            27     orcl_raw2number(zero, sizeof(zero), r);
            28     gmp_snprintf(buf, sizeof(buf), "%Ff\n\t%.*Ff(%d digits)", r, n, r, n);
            29     printf("result: %s\n", buf);
            30     printf("\t"); mpf_out_str(NULL, 10, 0, r); printf("\n");
            31     mpf_clear(r);
            32 
            33     //test actual max value:99999(the number of 9 is 38)
            34     unsigned char max_data[] = {0xd3,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64};
            35     orcl_raw2number(max_data, sizeof(max_data), r);
            36     gmp_snprintf(buf, sizeof(buf), "%Ff\n\t%.*Ff(%d digits)", r, n, r, n);
            37     printf("result: %s\n", buf);
            38     printf("\t"); mpf_out_str(NULL, 10, 0, r); printf("\n");
            39     mpf_clear(r);
            40 
            41     //test actual min value:-99999(the number of 9 is 38)
            42     unsigned char min_data[] = {0x2c,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x66};    
            43     orcl_raw2number(min_data, sizeof(min_data), r);
            44     gmp_snprintf(buf, sizeof(buf), "%Ff\n\t%.*Ff(%d digits)", r, n, r, n);
            45     printf("result: %s\n", buf);
            46     printf("\t"); mpf_out_str(NULL, 10, 0, r); printf("\n");
            47     mpf_clear(r);
            48 
            49     clear_mpf_globals();
            50 
            51     //test max oracle number value
            52     mpf_init2(r, 256);
            53 
            54     mpf_set_str(r, "1e125", 10);
            55     mpf_out_str(NULL, 10, 0, r); printf("\n");
            56     gmp_printf("%Ff\n", r);
            57     
            58     //test min oracle number value
            59     mpf_set_str(r, "-1e125", 10);
            60     mpf_out_str(NULL, 10, 0, r); printf("\n");
            61     gmp_printf("%Ff\n", r);
            62 
            63     mpf_clear(r);
            64 
            65     return 0;
            66 }
               輸出如下
               
            posted on 2020-05-08 12:23 春秋十二月 閱讀(962) 評論(0)  編輯 收藏 引用 所屬分類: Database
            人妻精品久久久久中文字幕69| 久久久精品久久久久特色影视| 中文字幕无码免费久久| 狠狠色丁香久久婷婷综合_中| 久久久久亚洲AV无码专区体验| 青青青青久久精品国产| 久久久久九九精品影院| 精品久久人人妻人人做精品 | 欧美一级久久久久久久大片| 日批日出水久久亚洲精品tv| 欧美午夜精品久久久久免费视| 国产69精品久久久久99| 久久国产欧美日韩精品| 香蕉久久夜色精品国产小说| 久久久久久国产精品无码下载| 99久久精品九九亚洲精品| 伊人久久大香线蕉亚洲| 久久精品国产亚洲av瑜伽| 精品久久久噜噜噜久久久| 国产精品久久久久蜜芽| 精品无码人妻久久久久久| 久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口 | 一级做a爰片久久毛片免费陪| 久久精品视频网| 中文字幕乱码人妻无码久久| 久久免费视频6| 国产精品99久久久久久www| 亚洲精品国产字幕久久不卡| 综合久久精品色| 久久人人超碰精品CAOPOREN | 亚洲国产精品嫩草影院久久| 亚洲狠狠综合久久| 国内精品久久久久久野外| 久久亚洲AV成人无码国产| 性欧美丰满熟妇XXXX性久久久| 少妇久久久久久被弄到高潮| 日韩va亚洲va欧美va久久| 要久久爱在线免费观看| 色播久久人人爽人人爽人人片AV| 无码人妻少妇久久中文字幕 | 97久久久精品综合88久久|