【C/C++】整数及乘积的溢出问题

文章目录

  • 一、为什么会溢出?
  • 二、怎样解决?
  • 三、看个例题
  • 四、补充:scanf和cin的区别

一、为什么会溢出?

整数乘积的溢出问题是指两个整数相乘得到的结果超过了所能表示的数据类型的范围。

在计算机中,整数的表示是有限的,即存在一个最大值和最小值。当进行乘法运算时,如果结果超出了整数的表示范围,就会发生溢出。这种情况下,计算结果将不再准确,并且可能导致数据丢失或错误的计算结果。

比如:int类型,C 语言标准规定了 int 类型必须至少能表示 -32767 到 32767 之间的整数,也就是说,int 类型的最小值和最大值范围为 -215 到 215-1。

一般而言,int 类型在 32 位操作系统上占用 4 个字节(32 位),在 64 位操作系统上占用 8 个字节(64 位)。使用 limits.h 头文件可以查看当前编译器中 int 类型的最大值和最小值。

#include<iostream>
#include <limits.h>
using namespace std;int main()
{printf("INT_MIN: %d\n", INT_MIN);printf("INT_MAX: %d\n", INT_MAX);system("pause");return 0;
} 

在这里插入图片描述
至于INT_MIN的值为什么是-2147483648,原因是:

在 32 位系统中,int 类型通常占据 4 个字节,即 32 位,而最小的带符号整数(-2^31)的二进制补码表示恰好对应于 -2147483648。

二、怎样解决?

可以使用更大范围的整数类型,比如 long long 或者 int64_t 等,以支持更大范围的数值计算。

根据取值范围,灵活选用整数类型:
整型数据类型及其取值范围详解

三、看个例题

求 a 的 b 次方对 p 取模的值,其中 0≤a,b,c≤109, c>0

  • 用c++写:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b,c;int main(){cin >> a >> b >> c;ll ans = 1;while (b) {if(b&1) {ans = ans * a % c;} a = a * a % c;b /= 2;  // 将指数右移一位}cout << ans % c << endl;return 0;
}

这里用long long类型来表示a,b,c三个数,防止整数溢出,同时用到了快速幂算法,防止两整数相乘的结果发生整数溢出。

快速幂算法通过对指数 y 进行二进制拆分,将指数的幂运算转化为多个底数的平方运算,从而减少了计算次数,提高了算法效率。

  • 在 C 和 C++ 中,y & 1 表示对变量 y 的值和二进制数 1 进行按位与(AND)操作。具体来说,这个表达式会将 y 的二进制表示的最低位与 1 进行按位与运算,得到的结果为 0 或 1。

  • 如果 y 的最低位是 1,那么 y & 1 的结果就是 1;如果 y 的最低位是 0,那么 y & 1 的结果就是 0。

  • 这种操作通常用于判断一个整数是奇数还是偶数。因为二进制数的最低位为 1 表示奇数,为 0 表示偶数,所以 y & 1 可以快速判断 y 是奇数还是偶数。

  • c的写法: (和c++只有一点点区别,文末补充)
#include<stdio.h>
int main(){long long a,b,c,d=1;scanf("%ld %ld %ld",&a,&b,&c);while(b){if(b&1)	d=d*a%c;a=a*a%c;b>>=1;}printf("%ld",d%c);
}
  • python的写法
a, b, c = map(int, input().split())
print(pow(a, b, c))

但是如果python以下写法,数值很大的时候就会发生溢出。

a, b, c = map(int, input().split())
ans = pow(a, b) % c
print(ans)

虽然Python 中的整数类型是动态的,不会存在固定的最大值,但如果结果超出了 Python 能表示的范围,也会发生溢出。就比如pow(a, b) % c这一步,当a, b, c 很大的时候,也是会发生整数溢出。

但是python有个很方便的函数,就是pow()的用法

pow(a, b, c)

具体参数含义如下:
a:底数
b:指数
c:模数

这个函数返回值为 (a**b) % c 的结果。

例如,pow(2, 3, 5) 将返回 3,因为 2 的 3 次方是 8,然后对 5 取模的结果是 3。

pow(a, b, c)函数在需要进行大数运算并对结果取模的情况下非常有用。

四、补充:scanf和cin的区别

scanf() 是 C 语言中的输入函数,而 cin 是 C++ 中的输入流对象。它们之间有以下几个区别:

  1. 语言:scanf() 是 C 语言的函数,而 cin 是 C++ 的输入流对象。

  2. 输入方式:scanf() 是使用格式化字符串来指定输入格式,可以通过不同的格式说明符(如 %d%f%s 等)来读取不同类型的数据。而 cin 使用运算符重载和类型推断来直接从标准输入流中读取数据,不需要显式指定输入格式。

  3. 错误处理:scanf() 在读取输入时需要注意错误处理,因为它不能自动处理输入格式不匹配或类型不正确的情况。而 cin 可以检测到输入类型不匹配等错误,并提供相应的错误处理机制,比如将输入流置于错误状态,清除错误标志等。

  4. 输入缓冲:scanf() 函数对输入的处理是基于缓冲区的,它会将输入数据读取到缓冲区中,然后根据格式字符串进行解析。而 cin 对象则是基于流的输入,它会逐个字符地从输入流中读取并解析数据,不需要缓冲区。

  5. 输入分隔符:scanf() 默认以空格、制表符、换行符等作为输入分隔符,可以通过格式化字符串来指定不同的分隔符。而 cin 默认以空格、制表符、换行符等作为输入分隔符,但它还提供了更灵活的方式来处理不同的输入分隔符。

总的来说,scanf() 是 C 语言中的函数,使用格式化字符串来指定输入格式,而 cin 是 C++ 中的输入流对象,使用运算符重载和类型推断来直接从标准输入流中读取数据,并提供更灵活的错误处理机制。两者在输入方式、错误处理、缓冲处理和输入分隔符上有所不同。

ps:如若文章有误,感谢指正!(づ ̄3 ̄)づ╭❤~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/460859.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2月7日作业

分别通过select、多进程、多线程实现一个并发服务器 #include <myhd.h> #define IP "192.168.250.100" #define PORT 8888 int deal_cli_msg(int newfd,struct sockaddr_in cin) {char buf[128] "";while(1){bzero(buf,sizeof(buf));int res recv…

Java完整版宿舍管理

项目技术&#xff1a; springboot layui idea mysql5.7 jdk1.8 maven3 有需要该项目的小伙伴可以私信我你的Q。 功能描述&#xff1a; &#xff08;1&#xff09;基本信息管理 基本信息分为学生信息和宿舍信息两部分&#xff0c;其功能是负责维护这些信息&#xff0c…

Ubuntu22.04 gnome-builder gnome C 应用程序习练笔记(二)

gnome-builder创建的程序&#xff0c;在工程树中有三个重要程序&#xff1a;main主程序、application应用程序和window主窗口程序。main整个程序的起始&#xff0c;它会操作application生产应用环境&#xff0c;application会操作window生成主窗口&#xff0c;于是就有了 appli…

CoreSight学习笔记

文章目录 1 Components1.1 ROM Table 2 使用场景2.1 Debug Monitor中断2.1.1 参考资料 2.2 Programming the cross halt2.2.1 编程实现2.2.2 参考资料 2.3 CTI中断2.3.1 编程实现2.3.1.1 准备工作2.3.1.2 触发中断2.3.1.3 中断响应 2.3.2 参考资料 1 Components 1.1 ROM Table…

AOP相关

AOP相关 什么是AOP&#xff1f; 常见的场景 记录操作日志 缓存处理 spring内置事务处理 AOP记录操作日志 定义切点表达式&#xff0c;确定要记录的方法 找到方法中有log注解的方法 获得方法 获得方法的参数 spring中的事务实现 spring中的事务分声明式事务和编程式事务…

巴菲特经典演讲:这些人只关注两个数字,便取得了成就

1984年&#xff0c;为纪念格雷厄姆&#xff08;Benjamin Graham&#xff09;和多德&#xff08;Daved L. Dodd&#xff09;所合著的《证券分析》出版五十周年&#xff0c;巴菲特应哥伦比亚大学邀请&#xff0c;进行了一次题为《格雷厄姆-多德式的超级投资者》&#xff08;The S…

[VulnHub靶机渗透] WestWild 1.1

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

#Js篇:js里面递归的理解

定义&#xff1a; 递归是一种编程技术&#xff0c;它是指一个函数在其定义内部调用自身的过程。 特点&#xff1a; 一个问题可以分解为更小的问题用同样的方法解决&#xff1b;分解后的子问题求解方式一样&#xff0c;不同的是数据规模变小&#xff1b;存在递归终止条件 作…

Springboot根据环境读取application配置文件

目录 1. 首先创建两个不同配置文件 2. pom.xml 配置文件 3. 指定环境 4. 最后启动测试 1. 首先创建两个不同配置文件 分别为开发环境和生产环境 application-dev.properties 和 application-prod.properties application-dev.properties 配置为 1931 端口 application-pro…

[leetcode] 31. 下一个排列

文章目录 题目描述解题方法两遍扫描java代码复杂度分析 题目描述 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下…

可靠性测试

1 软件可靠性测试 软件可靠性概述 可靠性&#xff08;reliability&#xff09;是指产品在规定的条件下和规定的时间内完成规定功能的能力。 固有可靠性是通过设计、制造赋予产品的可靠性&#xff1b;使用可靠性既受设计、制造的影响&#xff0c;又受使用条件的影响。一般使用可…

(43)找出中枢整数

文章目录 每日一言题目解题思路法一&#xff1a;法二&#xff1a; 代码法一&#xff1a;法二&#xff1a; 结语 每日一言 即使慢&#xff0c;驰而不息&#xff0c;纵令落后&#xff0c;纵令失败&#xff0c;但一定可以达到他所向往的目标。——鲁迅 题目 题目链接&#xff1a…