• <知识整理>2019清北学堂提高储备D4


    今天主要讲一下数学的知识。

      一、进制转换:

          十进制到k进制:短除法:顺除至0,逆序取余。

          k进制转十进制:乘权相加。

          常见进制:四进制(对应2位二进制)、八进制(对应3位二进制)、十六进制(对应4位二进制,A表示10,B表示11,...,F表示15)

          常见进制在c++中的表示:二进制:前加0b;八进制:前加0;十六进制:前加0x。 

          小提示:只有十进制下的读数是“...几千几百...”的读法,其他进制都直接把数位上的数读出来就行辣。

      二、高精度 

          常见数据类型的范围:int:[-232,232-1]

                    long long :[-263,263-1]≈1020

          那么对于超过这些数据范围的数怎么办呢?(我才不说有个int_128) ,这时候就要用到高精度了。高精度就是用来解决大整数的运算。

          有关高精度加减乘除的基本讲解可见我的另一篇博客,这里只说说新的东西。

        https://www.cnblogs.com/InductiveSorting-QYF/p/10679946.html(博客地址)

          对于高精度,我们可以写好高精度重载运算符的模板,码程序时先用int型码好程序,用小数验证算法正确性后再将int改成高精型(结构体的运用),否则程序出错后难以判断出错在算法还是高精。对于初始化结构体,可用构造函数(面向对象的知识),简单来说就是一个不写类型、函数名为结构体类型名、写在结构体里的函数,该函数每当有该结构体对象声明时都会被调用一次。(与此对应的还有析构函数,有兴趣的OIER可以看看:https://www.runoob.com/cplusplus/cpp-constructor-destructor.html(C++ 类构造函数 & 析构函数

    )    配合C++中struct和class的区别  食用更佳)

          代码如下:

     1 struct gaojing
     2 {
     3     int z[100010];
     4     int l;
     5     gaojing()
     6     {
     7         l=1;
     8         memset(z,0,sizeof(z));
     9     }
    10 }

          重载运算符(以加号为例)代码:

     1 gaojing operator+(gaojing a,gaojing b)
     2 {
     3     gaojing c;
     4     
     5     int l = max(a.l,b.l);
     6     for (int i=0;i<l;i++)
     7     {
     8         c.z[i] += a.z[i] + b.z[i];
     9         c.z[i+1] += c.z[i] / 10;
    10         c.z[i] = c.z[i] % 10;
    11     }
    12     if (c.z[l] != 0) l++;
    13     c.l = l;
    14     
    15     return c;
    16 }

         细心的同学会发现,其实这个有个问题。想必大家都知道函数传值调用与传址调用的区别:传值调用不会改变主调用函数中变量的值,而传址调用则会改变。同时由此发现每次传值调用都会拷贝一份主调用函数的变量。这个变量小的话还好,但如果要是很大的数组的话,必然会增加额外的时间复杂度,而且一个程序的加法运算又很多,那么调用函数的次数也很多,总的一看,时间就被浪费许多了。  

          怎么处理这种情况?

          既然传值调用不行,传址调用就好了嘛。同时为了防止打码手抖改掉加数的值,可在形参表中加上const。正确代码如下:

     1 gaojing operator+(const gaojing &a,const gaojing &b)
     2 {
     3     gaojing c;
     4     
     5     int l = max(a.l,b.l);
     6     for (int i=0;i<l;i++)
     7     {
     8         c.z[i] += a.z[i] + b.z[i];
     9         c.z[i+1] += c.z[i] / 10;
    10         c.z[i] = c.z[i] % 10;
    11     }
    12     if (c.z[l] != 0) l++;
    13     c.l = l;
    14     
    15     return c;
    16 }

          其他的运算符重载大都与此相差不大。这里再说明一下输入输出的重载:

    代码如下:

     1 struct gaojing
     2 {
     3     int z[100010];
     4     int l;
     5 
     6     friend istream& operator>>(istream &cin, gaojing &a)
     7     {
     8         static char s[100010];
     9         cin >> s;
    10         int l=strlen(s);
    11         for (int i=0;i<l;i++)
    12             a.z[i] = s[l-i-1] - '0';
    13         a.l = l;
    14     
    15         return cin;
    16     }
    17     
    18     friend ostream& operator<<(ostream &cout,const gaojing &a)
    19     {
    20         for (int i=a.l-1;i>=0;i--)
    21             cout << a.z[i];
    22         
    23         return cout;
    24     }
    25 };

    输入/出的重载有点特别。它们需要写在struct的定义中。(好像因为是友联函数什么的,就是那个friend啦。),而且重载的是“<<”和">>"。istream和ostream是输入和输出流,函数形参表的意思差不多是:将cin里的数读到a中;将a里的数输出到cout中。只能是cin和cout,不能scanf和printf。(百度警告)。重载完各种运算符后,就可以把int型扔掉了,写程序真方便(高精模板真多)

        最后TIP:以上提及的四则运算符都没有考虑有负数出现的情况,有负数需另考虑。

          

        

            

          

  • 相关阅读:
    Troubleshooting a Jedis Connection Pool Error
    com.mysql.cj.jdbc.exceptions.CommunicationsException
    springboot tomcat连接池
    Spring官方文档
    Troubleshooting-Spring-RestTemplate-Requests-Timeout
    Linux进程和端口命令总结
    Git及GitLab使用手册
    MySQL数据库命令大全
    两天时间,实现自己的 Promise
    vue-cli3.0搭建服务端渲染SSR
  • 原文地址:https://www.cnblogs.com/InductiveSorting-QYF/p/10800764.html
Copyright © 2020-2023  润新知