• 处理超长位数的数


     float和double型数据分别是单精度和双精度型数,他们的取值分别是3.4E+10的负38次方到3.4E+10的38次方,和1.7E+10的负308次方到1.7E+10的308次方。
    那么float 6-7位的有效数字怎么能装下如3.4E+10的负38次方同是double型娄15-16位的有效数字怎么能装下如1.7E+10的负308次方的数呢。这不是相矛盾吗?
    回答:不矛盾。float 6-7位 指的是 有效数字的位数(精度) 而不是 数值 大小。例如,3.14159267有9位有效数字,数值却在3~4之间,而350有3位数字,大小却在300~400之间。所以说float数能达到3.4E+10,但是它的有效数字位数只能达到6-7位,如果3.14159267赋值给一个float变量,那么精度将会减小。例如
    float a=3234567.1;
    float b=3234567;
    if( a==b )
        printf("YES");
    else
        printf("NO");
    将输出YES,因为a末尾的11超出了float 只能达到6-7位的精度。(如果a=1234567.1;b=3234567)输入结果将是NO,为什么呢?这就要我们分析:超出精度的部分怎么处理?不是四舍五入,而是二进制位的丢失。所以说有时候能达到6位的精度,有时候能达到7位的精度,取决于该数的二进制表示。
    那么我们就想怎么表示超长位数,超大精度的数字呢?比如123456789123456789123456789(超长30位的大整数),比如3.14159012345678901234567890123(超高精度30位的小数),这么长的数字,long float都存不下来,这就要借助于“字符串”或者“字符数组”了。
    unsigned __int64 n;
    无符号__int64类型的变量n,最大值超过了1234567892345678912(20位),可达到约1.8E+19,平常来说应该够用了。__int64类型的数据不能用C++里面的cout来输出,应该是cout没有重载这个类型,如果用printf来输出,显然%d, %f, %l都无法满足20位的精度,网上查到VC6下可以用printf("%I64d ", n);但是支持的位数不超过20,经我测试,大概超过9.23E+18 输出的结果就会出错了。那么最好的办法是将“长位数”转换成字符串,如下:
    char buffer[65];
    printf("%s", _ui64toa(n, buffer,10) );
    函数_ui64toa就是负责将n转换成字符串的,存入字符数组buffer[65]中,10代表转换成10进制。
     转换数字为字符串:
    #include <stdlib.h>
    #include <stdio.h>
    int main( void )
    {
       char buffer[65];
       int r;
       for( r=10; r>=2; --r )
       {
         _itoa( -1, buffer, r );
         printf( "base %d: %s (%d chars) ", r, buffer, strlen(buffer) );
       }
       printf( " " );
       for( r=10; r>=2; --r )
       {
         _i64toa( -1L, buffer, r );
         printf( "base %d: %s (%d chars) ", r, buffer, strlen(buffer) );
       }
       printf( " " );
       for( r=10; r>=2; --r )
       {
         _ui64toa( 0xffffffffffffffffL, buffer, r );

         printf( "base %d: %s (%d chars) ", r, buffer, strlen(buffer) );
       }
    }
    Output
    base 10: -1 (2 chars)
    base 9: 12068657453 (11 chars)
    base 8: 37777777777 (11 chars)
    base 7: 211301422353 (12 chars)
    base 6: 1550104015503 (13 chars)
    base 5: 32244002423140 (14 chars)
    base 4: 3333333333333333 (16 chars)
    base 3: 102002022201221111210 (21 chars)
    base 2: 11111111111111111111111111111111 (32 chars)
    base 10: -1 (2 chars)
    base 9: 145808576354216723756 (21 chars)
    base 8: 1777777777777777777777 (22 chars)
    base 7: 45012021522523134134601 (23 chars)
    base 6: 3520522010102100444244423 (25 chars)
    base 5: 2214220303114400424121122430 (28 chars)
    base 4: 33333333333333333333333333333333 (32 chars)
    base 3: 11112220022122120101211020120210210211220 (41 chars)
    base 2: 1111111111111111111111111111111111111111111111111111111111111111 (64 chars)
    base 10: 18446744073709551615 (20 chars)
    base 9: 145808576354216723756 (21 chars)
    base 8: 1777777777777777777777 (22 chars)
    base 7: 45012021522523134134601 (23 chars)
    base 6: 3520522010102100444244423 (25 chars)
    base 5: 2214220303114400424121122430 (28 chars)
    base 4: 33333333333333333333333333333333 (32 chars)
    base 3: 11112220022122120101211020120210210211220 (41 chars)
    base 2: 1111111111111111111111111111111111111111111111111111111111111111 (64 chars)
    PS:可以用这个函数来将10进制整数转换成二进制字符串;

    int main( void )

    {

       char buffer[65];

       _itoa( 12, buffer, 2 );

       printf( "base %d: %s (%d chars) ", r, buffer, strlen(buffer) );

    }
    还有一种方法是自己定义字符数组存放 超长位数的数,小数点也是可以解决的,然后自己定义这些 字符串形式的超长数之间的运算法则并重载运算符,据说这样做运算效率还是蛮高的。

  • 相关阅读:
    SparkSQL访问Hive源,MySQL源
    SparkStreaming算子操作,Output操作
    JVM 配置常用参数和常用 GC 调优策略
    SparkStreaming与Kafka,SparkStreaming接收Kafka数据的两种方式
    consul service
    Centos7 vnc
    Centos7 創建快捷方式
    Consul Session
    python consul
    python 形参
  • 原文地址:https://www.cnblogs.com/zhangyongjian/p/3633368.html
Copyright © 2020-2023  润新知