• <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>
            隨筆-159  評論-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 春秋十二月 閱讀(946) 評論(0)  編輯 收藏 引用 所屬分類: Database
            伊人久久大香线蕉av不卡| 国产亚洲精品美女久久久| 久久青草国产手机看片福利盒子 | 久久久噜噜噜久久中文字幕色伊伊 | 久久精品欧美日韩精品| 久久国产免费观看精品| 久久乐国产精品亚洲综合| 久久精品国产乱子伦| 久久精品草草草| 亚洲伊人久久成综合人影院| 亚洲国产精品高清久久久| 狠狠色婷婷综合天天久久丁香| 精品国产综合区久久久久久| 久久久久久久久久久久久久| 国产福利电影一区二区三区久久老子无码午夜伦不 | 少妇熟女久久综合网色欲| 久久香蕉国产线看观看精品yw| 亚洲国产精品婷婷久久| 国产精品美女久久福利网站| 久久99国产亚洲高清观看首页 | 久久亚洲中文字幕精品一区| 99re久久精品国产首页2020| 久久亚洲天堂| 国产成人香蕉久久久久| 99久久精品国内| 色欲久久久天天天综合网| 久久久WWW成人免费精品| 久久国产精品-国产精品| 一本色道久久88—综合亚洲精品| 久久丝袜精品中文字幕| 曰曰摸天天摸人人看久久久| 蜜臀av性久久久久蜜臀aⅴ | 精品国产乱码久久久久软件| 久久久久国产成人精品亚洲午夜| 久久久久人妻一区精品性色av| 亚洲午夜福利精品久久| 久久久久国产精品三级网| 久久精品国产国产精品四凭| 国产亚洲美女精品久久久| 久久93精品国产91久久综合| 久久e热在这里只有国产中文精品99|