• <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
            2021久久国自产拍精品| 中文国产成人精品久久不卡| 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲 | 99久久精品无码一区二区毛片 | 2020久久精品亚洲热综合一本| 中文字幕久久亚洲一区| 久久亚洲私人国产精品vA| 免费观看久久精彩视频 | 国产精品久久久久国产A级| 伊人久久大香线焦综合四虎| 午夜精品久久影院蜜桃| 人妻丰满AV无码久久不卡| 国产精自产拍久久久久久蜜| 无码久久精品国产亚洲Av影片| 国产AV影片久久久久久| 亚洲av日韩精品久久久久久a | 亚洲av伊人久久综合密臀性色| 欧美日韩中文字幕久久伊人| 久久www免费人成看片| 国产精品成人无码久久久久久| 中文字幕乱码人妻无码久久| 国产成人久久久精品二区三区| 免费精品久久天干天干| 久久国产成人精品国产成人亚洲| 亚洲人成伊人成综合网久久久 | 一本久久免费视频| 国产呻吟久久久久久久92| AV狠狠色丁香婷婷综合久久| 国色天香久久久久久久小说| 日韩AV毛片精品久久久| 国产精品狼人久久久久影院 | 国产91久久精品一区二区| 久久久噜噜噜久久中文字幕色伊伊| 久久99久久成人免费播放| 久久精品国产影库免费看| 国产成人精品久久免费动漫| 久久精品人人做人人妻人人玩| 亚洲精品国产美女久久久| 久久AV高潮AV无码AV| 无码人妻久久久一区二区三区| 久久精品成人欧美大片|