• <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
            精品国产乱码久久久久软件| 欧美日韩精品久久久久| 久久精品九九亚洲精品| 国产A级毛片久久久精品毛片| 欧美喷潮久久久XXXXx| 亚洲精品高清久久| A级毛片无码久久精品免费| 俺来也俺去啦久久综合网| 欧美伊人久久大香线蕉综合69 | 久久综合给合久久国产免费| 久久久精品一区二区三区| 亚洲伊人久久综合影院| 国产精品久久久久久吹潮| 亚洲国产日韩欧美久久| 国产亚洲婷婷香蕉久久精品| 香蕉久久夜色精品国产尤物| 91精品国产综合久久香蕉| 熟妇人妻久久中文字幕| 久久国产三级无码一区二区| 99国产精品久久| 少妇久久久久久被弄高潮| 香蕉久久AⅤ一区二区三区| 欧美精品一本久久男人的天堂| 亚洲精品高清国产一线久久| 久久人与动人物a级毛片| 久久国产午夜精品一区二区三区| 久久AV高清无码| 久久精品无码专区免费青青| 亚洲国产天堂久久久久久| 精品熟女少妇aⅴ免费久久| 一本大道久久a久久精品综合| 久久精品国产亚洲av日韩| 少妇久久久久久久久久| 亚洲AV日韩精品久久久久久| 亚洲国产精品无码久久久不卡| 亚洲美日韩Av中文字幕无码久久久妻妇 | 亚洲精品高清国产一久久| 777米奇久久最新地址| www.久久热.com| 亚洲综合精品香蕉久久网97| 国产精品嫩草影院久久|