【算法题】机试指南-数学问题篇

本文仅供个人学习使用,免费分享。每日更新,建议关注收藏!
目前[机试指南]本系列已经达到字数10w+,所以按原每个章节拆开发布,点击目录跳转。

本站友情链接:

  1. c/c++算法题指南
    严书代码
    c/c++大复习1
    c/c++大复习2
  2. python算法题指南
    牛客华为机试103精华
    python输入输出大全
    python语法
    PAT甲级真题刷题笔记 共179道
  3. python官方文档
    python官方文档
  4. 机试指南系列
    基础篇
    贪心篇
    递归分治搜索篇
    数据结构进阶篇(树/图/优先队列)
    数学问题篇
    动态规划篇
    STL篇

数学问题

负数的%

如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数q和r,满足a = q * d + r 且0 <= |r| < |d|。其中q被称为商,r被称为余数。即a%d=r
例如:-10%3=2 [python版,因为python是向-∞取整]
因为-10=3*(-4)+2
例如:-10%3=-1 [c版,因为c是向0取整]
因为-10=3*(-3)±1

位运算

求n的第k位数字: n >> k & 1
返回n的最后一位1:lowbit(n) = n & -n

有符号整数通常用补码来表示和存储,补码具有如下特征:

  1. 正整数的补码与原码相同;负整数的补码为其原码除符号位外的所有位取反后加 1;
  2. 可以将减法运算转化为补码的加法运算来实现。
  3. 符号位与数值位可以一起参与运算。

因为有符号整数用补码来表示,所以算法也可以推广到 0 和负数。
若题目要求不能使用运算符做加减法,则就需要位运算了。
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 0 (进位)

可以得到结论:关于整数a,b
不考虑进位情况下,加法为a^b (异或)
所有需要进位的位即 a&b,进位后的进位结果为(a&b)<<1
在这里插入图片描述

https://www.lintcode.com/problem/1276/

class Solution:
    """
    @param a: 
    @param b: 
    @return: return an integer
    """
    MASK1 = 4294967296  # 2^32 (1+31个0)
    MASK2 = 2147483648  # 2^31 (1+30个0)
    MASK3 = 2147483647  # 2^31-1 (30个1)

    def get_sum(self, a: int, b: int) -> int:
        #print(bin(a),bin(b),bin(-11),((2**32)-1)== (self.MASK2 ^ self.MASK3))      
        a %= self.MASK1
        b %= self.MASK1 
        #b是负数时,取模后 新b=原b+MASK1
        #print(bin(a),bin(b),b,bin(-1*self.MASK1))
        while b != 0:
            carry = ((a & b) << 1) % self.MASK1 #进位
            a = (a ^ b) % self.MASK1 #未带进位的加法
            b = carry
            #print('carry,a',bin(carry),bin(a),a-self.MASK1+1)  
        if a & self.MASK2:  # 满足则是负数 第一位为1
            #正确结果=(a-MASK1) 之前加过MASK1 现在减回来
            #print((bin(a ^ -1*(self.MASK1))))
            return (a ^ -1*(self.MASK1))
        #负数部分的原理就是 先把负数+MASK1变成正数,再加a,之后再减掉MASK1
        
        else:  # 正数
            return a
#a=Solution()
#Solution.get_sum(a,16,-27)

由打印输出也可以发现,python中表示负数的二进制是在其正数的二进制前面加上符号(代替理论中的符号位1,更加不易混淆),但当真实计算负数时还是底层用补码来算的,如在代码中的-1*(self.MASK1),其底层的二进制实际上是对[符号位0+self.MASK1]取反+1得到,但顶层打印出来的都是-0b10000000000000000000000000000000
self.MASK1的二进制是0b10000000000000000000000000000000

颠倒给定的( 最多32 位)无符号整数的二进制位。并输出这个数的十进制。

class Solution:
    def reverse_bits(self, n: int) -> int:
        rev = 0
        #print(bin(n))
        for i in range(32):
            if n <= 0: break
            rev |= (n & 1) << (31 - i)
            n >>= 1
        return rev

www.lintcode.com/problem/664

class Solution(object):
    def countBits(self, num):
        """
        :type num: int
        :rtype: List[int]
        """
        #动态规划dp
        res = [0] * (num + 1)
        for i in xrange(1, num + 1):
            res[i] = res[i >> 1] + (i & 1)
        return res

进制转换

x = b 0 ∗ 2 0 + b 1 ∗ 2 1 + . . . + b n ∗ 2 n b 0 = x x / 2 = b 1 ∗ 2 0 + . . . + b n ∗ 2 n − 1 x=b_0*2^0+b_1*2^1+...+b_n*2^n\\ b_0=x%2 \\x/2=b_1*2^0+...+b_n*2^{n-1} x=b020+b121+...+bn2nb0=xx/2=b120+...+bn2n1
总结来说就是利用好【 % ,/】,【*,^】运算。
十进制转2进制,先%2,再/2,不断重复n次(n是数字位数)或者该数为0时停止。

上述这个适用于正整数,负整数详见[🔗链接]

www.lintcode.com/problem/365/

class Solution:
    """
    @param num: An integer
    @return: An integer, the number of ones in num
    """
    def count_ones(self, num: int) -> int:
        # write your code here
        result=[]
        temp_num=num
        while(len(result)<32 or temp_num ):
            if(num>=0):
                result.append(int(temp_num%2))
            else: 
                temp=(0 if int(temp_num%2)==1 else 1)
                result.append(temp)
            temp_num=int(temp_num/2)
        
        
        
        if(num<0):
            result=result[::-1]
            result[-1]+=1
            for i in range(len(result)-1,-1,-1):
                #print(result)
                if(result[i]>=2):
                    result[i]-=2
                    if(i>-2):result[i-1]+=1
                else: break
        #print(result)
        return(result.count(1))

#大佬做法更简洁
class Solution:
    # @param num: an integer
    # @return: an integer, the number of ones in num
    def countOnes(self, num):
        # write your code here
        total = 0
        for i in range(32):
            total += num & 1
            #print(bin(num),num & 1,num>>1)
            num >>= 1
        return total

例题6.1 二进制数(北京邮电大学复试上机题) http://t.cn/AiCuKTOv

import sys
for line in sys.stdin:
    a = int(line)
    print(bin(a)[2:])

例题6.2 进制转换(清华大学复试上机题) http://t.cn/AiCuoPRO
该题是30位的数字,只能用字符串来模拟。取字符串最后一位last转换为数字取模,再调用编写好的字符串除法功能。
字符串除法功能 同在纸上进行除法运算一样 ,字符串从高到低逐位除以除数;如果不能整除,则保留余数,余数*10+低一位,直至每一位都处理过。可能会在左边前置多余的0,只需取首个非0位以及之后的字符串。
0154
----- 即divided函数的思想
8丿1234

#include<iostream>
#include<string>
#include<vector>
using namespace std;
 
// 用于将字符串表示的大整数除以 x,并返回商
string Divided(string str, int x) {
    int reminder = 0;
    for (int i = 0; i < str.size(); i++) {
        int current = str[i] - '0' + reminder * 10;  // 将当前位转换为整数并加上上一次的余数
        str[i] = current / x + '0';  // 将商转换为字符并保存到字符串中
        reminder = current % x;  // 更新余数
    }
    int pos = 0;
    while (str[pos] == '0') {
        pos++;  // 去掉结果字符串开头多余的零
    }
    str = str.substr(pos);  // 更新结果字符串
 
    return str;
}
 
int main() {
    string s;
    while (cin >> s) {
        vector<int> binary;  // 用于存储二进制数的每一位
        while (s.size() != 0) {
            int last = s[s.size() - 1] - '0';  // 获取字符串最后一位的整数值
            binary.push_back(last % 2);  // 将最后一位对2取余并保存到二进制数数组中
            s = Divided(s, 2);  // 将原字符串除以2,得到新的字符串
        }
        for (int i = binary.size() - 1; i >= 0; i--) {
            cout << binary[i];  // 从数组末尾开始输出二进制数,得到正确的二进制表示
        }
        cout << endl;
    }
 
    return 0;
}

例题6.3 十进制与二进制(清华大学复试上机题) http://t.cn/AiCuoHKg
对于一个十进制数A,将A转换为二进制数,然后按位逆序排列,再转换为十进制数B,我们称B为A的二进制逆序数。 例如对于十进制数173,它的二进制形式为10101101,逆序排列得到10110101,其十进制数为181,181即为173的二进制逆序数。
输入描述:
一个1000位(即10^999)以内的十进制数。
输出描述:
输入的十进制数的二进制逆序数。

#include<iostream>
#include<string>
#include<vector>
using namespace std;
 
// 例题6.3 KY26 10进制 VS 2进制 
 
// 字符串表示的大整数除法
string divide(string str, int x) {
    int reminder = 0;  // 余数
    for (int i = 0; i < str.size(); i++) {
        int current = reminder * 10 + str[i] - '0';  // 当前位的数值
        str[i] = current / x + '0';  // 更新当前位的值为商的字符表示
        reminder = current % x;  // 更新余数
    }
    int pos = 0;
    while (str[pos] == '0') {
        pos++;  // 移除前导零
    }
    return str.substr(pos);  // 返回除法结果,移除前导零
}
 
string multiple(string str, int x) {
    int carry = 0;  // 进位
    for (int i = str.size() - 1; i >= 0; i--) {
        int current = x * (str[i] - '0') + carry;  // 当前位的计算结果
        str[i] = current % 10 + '0';  // 更新当前位的值为计算结果的个位
        carry = current / 10;  // 更新进位
    }
    if (carry != 0) {
        str = "1" + str;  // 处理最终的进位
    }
    return str;
}
 
string Add(string str, int x) {
    int carry = x;  // 初始进位为 x
    for (int i = str.size() - 1; i >= 0; i--) {//从最右边开始相加,不断往左进位
        int current = (str[i] - '0') + carry;  // 当前位的计算结果
        str[i] = current % 10 + '0';  // 更新当前位的值为计算结果的个位
        carry = current / 10;  // 更新进位
    }
    if (carry != 0) {
        str = "1" + str;  // 处理最终的进位
    }
    return str;
}
 
int main() {
    string s;
    cin >> s;  // 输入十进制数
    vector<int> binary;  // 用于存放二进制逆序的每一位
    while (s.size() != 0) {
        int last = s[s.size() - 1] - '0';  // 取最后一位
        binary.push_back(last % 2);  // 将最后一位的余数(二进制的最低位)存入 vector
        s = divide(s, 2);  // 将十进制数除以 2,得到下一轮迭代的数值
    }
 
    // 将得到的 binary 中的按位逆序排列的二进制数转换为十进制数
    string res = "0";  // 初始化结果为 0
    for (int i = 0; i < binary.size(); i++) {
        res = multiple(res, 2);  // 将结果乘以 2,相当于左移一位
        res = Add(res, binary[i]);  // 加上当前位的值
    }
    cout << res << endl;  // 输出最终的二进制逆序数
   
    return 0;
}

例题6.4 进制转换2(清华大学复试上机题) http://t.cn/AiCuKG7E
输入的第一行包括两个整数:M和N( 2 ≤ M , N ≤ 36 2\leq M,N\leq36 2≤M,N≤36)
下面的一行输入一个数X,X是M进制的数,现在要求你将M进制的数X转换成N进制的数并输出。
首先应该用十进制作为中转,M->10->N

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;

/*
    题目描述:
        进制转换2
            从M进制转换到N进制
*/
string divide(string str, int x,int &reminder){//字符串除法,reminder是余数
    reminder = 0;
    for(int i = 0;i<(int)str.size();i++){
        int current = (str[i]-'0') + reminder*10;
        str[i] = (current/x)+'0';
        reminder = (current%x);
    }
    int pos = 0;
    while(str[pos] == '0') pos++;
    return str.substr(pos);
}

string mutiply(string str, int x){//字符串乘法,结果为10进制字符串
    int carry = 0;
    for(int i = str.size()-1;i>=0; i--){
        int current = x*(str[i]-'0')+carry;
        str[i] = (current%10)+'0';
        carry = current/10;
    }
    if(carry) str.insert(0,1,carry+'0');
    return str;
}

string add(string str, int x){//字符串加法,结果为10进制字符串
    int carry = x;
    for(int i = str.size()-1; i>=0; i--){
        int current = (str[i]-'0')+carry;
        str[i] = (current%10)+'0';
        carry = (current/10);
        if(!carry) break;
    }
    if(carry) str.insert(0,1,carry+'0');
    return str;
}

int ToInt(char c){//进制位值转换为int值
    if('0'<= c && c <= '9') return c-'0';
    if('A'<= c && c <= 'Z') return c-'A'+10;
} 

char ToChar(int x){//int值转换为进制位值
    if(x<10) return x+'0';
    else return (x-10)+'A';
}

int main(){
    int M,N;
    cin>>M>>N;
    string str;
    cin>>str;
    string decimal = "0";
    stack<char> answer;
    for(int i = 0;i<str.size();i++){ //转换为10进制
        decimal = mutiply(decimal,M);
        decimal = add(decimal,ToInt(str[i]));
    }
    while(decimal != ""){ //转换为N进制
        int bit;
        decimal = divide(decimal,N,bit); //bit作为余数被传回
        answer.push(ToChar(bit));
    }
    while(!answer.empty()){
        cout<<answer.top();
        answer.pop();
    }
    cout<<endl;
    return 0;
}

习题6.1 八进制(华中科技大学复试上机题) http://t.cn/AiCu0lHe
习题6.2 又一版A+B(浙江大学复试上机题) http://t.cn/AiCuOSWv
习题6.3 进制转换(北京大学复试上机题) http://t.cn/AiCuig9B
习题6.4 数制转换(北京大学复试上机题) http://t.cn/AiCu6ne4

最大公约数gcd&最小公倍数lcm

greatest common divisor
least common multiple
最大公约数gcd怎么求?

int gcd(int a,int b){
	if(b==0)return a;
	else return gcd(b,a%b);
}

最小公倍数lcm怎么求?用两数的乘积除以两数的gcd

例题6.5 最大公约数(哈尔滨工业大学复试上机题) http://t.cn/AiCuWLTS
例题6.6 最小公倍数 http://acm.hdu.edu.cn/showproblem.php?pid=1108

习题6.5 最简真分数(北京大学复试上机题) http://t.cn/AiCua2g8

质数=素数

只能被1和其本身整除。循环范围只需2到sqrt(n)即可
注意 x<2的肯定不是质数(素数)

那大范围的肯定会超时,怎么处理?【不定长的vector启动 或者primes[cnt++] 以及book[num]标记是否是素数】

  • 素数筛法
    范围2~n遍历,将每一个素数i的所有倍数(初始下标是i*i,更节约时间,一直判到max,max=sqrt(1e9))标记成非素数,book数组,初始化首先book[0]=book[1]=0;( 0,1都不是质数)

  • 增量式的使用素数筛法先求出2~10000内的素数,得到n后再看是否需要继续判断素数。

素数筛如何最优化?

  1. 素数一定是奇数,即从i=3开始,步长为2,i+=2
  2. 判断范围设置为[2,sqrt(n)],即i*i<=n,或者将int bound= sqrt(n),循环条件中不要重复计算增加复杂度
  3. 埃及筛的思想,当i判断为质数时,从i*i开始筛
  4. 欧拉筛,为了改进埃及筛中仍有重复筛掉的情况,保证每个非质数只被筛掉一次
    根据唯一分解定理,在这里插入图片描述
    可知,每个合数都有一个最小素因子。
  • 欧拉筛的基本思想是,让每个合数被其自身的最小素因子筛选,而不会被重复筛选。
  • 欧拉筛的框架和埃氏筛大致相同,每个素数的倍增过程都是从平方开始,就和前面埃氏筛优化方法一种一样,可以有效避免重复。而区别则在于第二层循环对倍增过程的操作。
    欧拉筛是用当前遍历到的数i(不一定是素数),去乘以已经在素数表中的素数。这样就保证了是以素数进行倍增,相较于使用任何数字进行倍增的情况,是已经优化过了。因为 i 是从小到大进行循环,会乘以前面的每一个素数,这就保证了每个素数的倍数都不会被错过。(由唯一分解定理也可证明:任何一个数都可用质数的乘积来表示,也是合数和质数的乘积)
    比如说此时i=6,前面有素数2,3,5。在欧拉筛中就是用2,3,5去乘以6,进行倍增筛除。
    举例说明:现在 i 循环到6,前面有素数2,3,5,这三个素数,都是从22,33,55开始倍增的,不会出现23,3*2的情况同时出现。
  • 怎么保证每个合数只被标记一次呢?
//这条代码是核心
if(i%prime[j]==0)
    break;

这条语句的加入,保证了每个合数只会被筛除一次,不会被重复筛除。为什么?
当 i 可以整除素数表中某个素数时,那么 i 就不需要在往后乘以其他素数了,因此往后乘以得到的结果,会以另外一种方式得到。
不再第二层循环中往后乘,而是跳出第二层循环,进入第一层循环。
等到第一层循环中循环到了合适的i=x时,就可以复现此时的结果。
因此这个合数并不会被忽略,而只是筛除的过程滞后了。
这样的滞后操作,保证了每一个合数,只被筛除一次,不会被重复筛除。
这种筛除方式,就是欧拉筛算法最前面提到的,使用最小素因子筛除。
因为构成数的质因数在左右区间是对称的,用公式解释就是
当 i%prime[j]==0时,i*prime[j+1]的结果,可以通过另外一种方式得到,比如x*prime[j]=i*prime[j+1]
i%prime[j]==0 说明prime[j]是i的一个素因子,并且是最小的素因子(因为是最早接触的素因子),所以i可以表示为a*prime[j]的形式
prime[j+1]是这种结果,往后的j+2,j+3等等也是类似的结果,因此这里就可以退出循环,等到i循环到x的时候,再把这个合数结果筛除。
这里合数到了prime[i]就退出了,因此后面的素数没有倍增的机会,即这个合数不会被其他素因子倍增到。(不会出现2*6=3*4=12等重复标记的情况出现)
因此每个合数只被其最小的素因子筛除,不会被其他素因子筛除,因此欧拉筛中每个合数只会被筛除一次,不会被重复筛除。

举例说明就是
比如i=12,此时素数数组中有素数2,3,5,7,11
2*12=24,把24筛除了,但是判定12可以整除2212的最小素因子(是因子,且是素数因子),此时循环退出。
为什么呢?
因为12*3=36这个结果可以通过12的最小素因子2,以其他方式得到。36这个结果,当x=18时可以通过18*2得到。同样的,后面的素数*12得到结果,也可以通过另外的x与2相乘得到。比如12*5=60,可以通过30*2得到

例题6.7 素数判定(哈尔滨工业大学复试上机题) http://t.cn/AiCuWE0Q

例题6.8 素数 http://t.cn/AiCulqtW
输入一个整数n(2<=n<=10000),要求输出所有从1到这个整数之间(不包括1和这个整数)个位为1的素数,如果没有则输出-1。

#include<iostream>
#include<cstdio>
#include<stack>
#include<vector>
using namespace std;
vector <int>prime;//保存质数
const int MAXN = 10001;
bool isPrime[MAXN];
void SearchS()   //素数筛选法找到2~10000之间的所有素数
{
 
    for(int i=0;i<MAXN;i++)
    {
        isPrime[i]=true;
    }
    isPrime[0]=false;
    isPrime[1]=false;
    for(int i=2;i<MAXN;i++)
    {
        if(!isPrime[i]){
            continue;//非质数则跳过
        }
        prime.push_back(i);  //是素数则加入数组里
        for(int j=i*i;j<MAXN;j+=i)
            isPrime[j]=false;
    }
}
int main(){
    int i,j,n;
    SearchS();
    int a[10000];
    while(scanf("%d",&n)!=EOF){
        if(n<=1) printf("-1\n");
        for(i=2,j=0;i<prime.size()&&prime[i]<n;i++)
        {
            if(prime[i]%10==1)
               a[j++]=prime[i];
        }
        for(i=0;i<j-1;i++)
            printf("%d ",a[i]);
        printf("%d\n",a[i]);
    }
}

习题6.6 Prime Number(上海交通大学复试上机题) http://t.cn/AiCulrSh

质因数

质数常用来分解质因数,每个数都是一个或几个质数相乘得到,这种质数称为质因数

x=p1^(e1) * p2^(e2)… * pn^(en)

步骤:

  1. 素数筛法,筛选可能的数据范围内的质数
  2. 遍历这些质数,判断是否是因数,如果是,则继续试除得到对应幂指数

例题6.9 质因数的个数(清华大学复试上机题) http://t.cn/Aip7J0Oo

#include<iostream>
#include<cmath>
using namespace std;
 
//例题6.9 质因数的个数
int main()
{
    int n;
    while (cin >> n) {
        int res = 0;
        for (int i = 2; i <= sqrt(n); i++) {
            while (n % i == 0) {
                res++;
                n /= i;
            }
        }
        if (n > 1) {
            res++;//还存在一个大于MAXN的因子,必为素因子,且幂指数必为1
        }
        cout << res << endl;
    }
 
    return 0;
}

n整数最多只存在一个大于MAXN的质因子,若存在,幂指数必为1

习题6.7 约数的个数(清华大学复试上机题) http://t.cn/Aip7dTUp
习题6.8 整除问题(上海交通大学复试上机题) http://t.cn/Aip7eHBD

快速幂

快速幂就是快速求a的b次方的方法
任何一个数字都可以分解成若干个2^k的和,先将其转化为2进制,就可以得到对应的次方数是多少。 如求 3 29 , 29 = 1 + 4 + 8 + 16 ,即 29 二进制为 11101 = 2 0 + 2 2 + 2 3 + 2 4 即 1 , 4 , 8 , 16 , 3 29 = 3 1 ∗ 3 4 ∗ 3 8 ∗ 3 16 如求 3^{29} ,29=1+4+8+16,即29二进制为11101=2 ^0+2 ^2+2 ^3+2 ^4即1,4,8,16,\\ 3^{29} =3^1*3^4*3^8*3^{16} 如求32929=1+4+8+16,即29二进制为11101=20+22+23+2414816329=313438316
对于题目中只输出最后几位的,庞大的数字很难运算存储,但a^b的后3位数只与a的后3位数和b有关,在求快速幂的过程中不断的对中间结果作1000取模

例题6.10 人见人爱A^B http://acm.hdu.edu.cn/showproblem.php?pid=2035

习题6.9 求root(N,K)(清华大学复试上机题) http://t.cn/AipAw4B1

矩阵、矩阵快速幂

矩阵其实运算原理相同,只不过将数换成了矩阵,1变成了单位矩阵,需要再定义一个函数作矩阵乘法

例题6.11 计算两个矩阵的乘积(哈尔滨工业大学复试上机题) http://t.cn/Aip450PJ
例题6.12 矩阵幂(北京邮电大学复试上机题) http://t.cn/Aip4T3HX
习题6.10 A+B for Matrices(浙江大学复试上机题) http://t.cn/Aipb7GBG
习题6.11 递推数列(清华大学复试上机题) http://t.cn/AipbZ2sS

高精度整数

数字非常大,如何处理和保存?c/c++有固定模版但过长,建议使用python直接用,因为它的数可以是任意大小
但要注意浮点数的运算,python对于整数的运算是完全准确的,也就是说我们可以先把小数点去除进行运算,之后再对所得结果做统一的处理。

浮点数运算输出17位长度的结果,但只有15个数字是准确的,也就是说python对于浮点数的运算具有摆尾性。

>>>3.141592653*1.234567898
3.8785094379864535
#转化成整数
>>>3141592653*1234567898
3878509437986453394

高精度浮点数可以使用decimal模块中的Decimal类来实现。Decimal类可以表示任意精度的小数,并提供了各种运算方法,包括加、减、乘、除、求幂等。

另一种方法:
decimal库是python的标准库,无需下载便可直接引用,首先开头通过import decimal引入decimal库。
使用Decimal类创建高精度浮点数的方式与普通浮点数略有不同,需要使用字符串形式表示数值。
注意:decimal.Decimal类型无法被转换为int类型,int(a*b)会报错,使用to_integral_value()方法将Decimal类型对象转换为了最接近的整数,然后使用int()函数将其转换为整数类型。这样可以保证精度不丢失。

import decimal
a=decimal.Decimal('3.141592653')
b=decimal.Decimal('1.234567898')
print(a*b)
print(type(a*b))
#输出
#3.878509437986453394
#<class 'decimal.Decimal'>

from decimal import Decimal
x = Decimal('3.14')
y = int(x.to_integral_value())
print(y)  # 输出 3

#特别长的数记得设置精度
decimal.getcontext().prec = n#指从头到尾最多可以保留1000位有效数字
Decimal('50.5679').quantize(Decimal('0.00')) #四舍五入保留两位小数
    

round函数

round(number, ndigits=None)

number表示要进行四舍五入的浮点数,ndigits表示要保留的小数位数,默认值为0,表示对整数进行四舍五入。
round()函数的工作原理如下:
如果ndigits参数未提供,则将number四舍五入到最接近的整数。
如果ndigits参数为正数,则将number四舍五入到指定的小数位数。
如果ndigits参数为负数,则将number四舍五入到指定的整数位数。
需要注意的是,round()函数的四舍五入规则是基于银行家算法实现的。该算法的基本思想是,如果要保留的位数的后一位为5,则将前一位向偶数舍入。【注意偶数】

from decimal import Decimal
a = Decimal('3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679')
b = round(float(a), 2)  # 对浮点数进行四舍五入,保留两位小数
c = Decimal(str(b))  # 将结果转换为高精度浮点数
print(c)  # 输出 3.14

需要注意round()函数的精度问题。由于浮点数的精度有限,因此在进行四舍五入运算时,可能会产生精度误差。如果需要进行高精度浮点数的四舍五入运算,可以使用decimal模块中的Decimal类型来处理。
如果需要使用round()函数对高精度浮点数进行四舍五入运算,可以先将高精度浮点数转换为字符串,再使用round()函数进行四舍五入,最后再将结果转换回高精度浮点数类型。

例题6.13 a+b(华中科技大学复试上机题) http://t.cn/AipaWiSG
例题6.14 N的阶乘(清华大学复试上机题) http://t.cn/AipaBKQJ
习题6.12 数字阶梯求和(哈尔滨工业大学复试上机题) http://t.cn/Aipak8BQ
习题6.13 大整数的因子(北京大学复试上机题) http://t.cn/AipaFCJE

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值