当前位置: 首页 > article >正文

C语言基本概念————讨论sqrt()和pow()函数与整数的关系

本文来源:C语言基本概念——讨论sqrt()和pow()函数与整数的关系.

C语言基本概念——sqrt和pow函数与整数的关系

  • 1. 使用sqrt()是否可以得到完全平方数的精确的整数平方根
    • 1.1 完全平方数的计算结果是否精确?
    • 1.2 为什么不会出现误差(如 `1.9999999`)?
    • 1.3 可能产生误差的情况
    • 1.4 总结
  • 2. 使用pow函数计算整数的幂能否得到精确的整数值
    • 2.1 **浮点数的精度限制**
    • 2.2 **隐式类型转换的陷阱**
    • 2.3 **实现依赖性问题**
    • 2.4 建议:如何安全计算整数幂?
    • 2.5 结论
    • 3. 举例


根据C标准,float类型必须至少能够表示6位有效数字,且取值范围至少是10-37〜10+37。其中,6位有效数字的要求意味着float类型必须能够精确表示如33.333333这样的数值;而取值范围的规定则使其能够方便地表示诸如太阳质量(2.0e30千克)、质子电荷量(1.6e-19库仑)等极大或极小的数值。

在大多数C语言实现中,单精度浮点数采用IEEE 754标准的32位表示法,其中尾数部分占23位(223= 8,388,608),相当于7位十进制数。这意味着float类型在转换为十进制后,最多可以保证7位有效数字的精度,完全满足C标准对6位有效数字的要求。需要注意的是,第7位之后的数字可能不准确。类似地,double类型的尾数占52位(252),可表示约16位十进制有效数字,或63位(263)时可表示约19位十进制有效数字。因此,double类型通常可以保证15-17位有效数字的精度。

sqrt()pow() 函数是 C 标准库 <math.h> 中的两个重要数学函数,其函数原型分别为:

double sqrt(double x);
double pow(double x, double y);

sqrt()函数用于计算x的平方根,而pow()函数用于计算x的y次幂。这两个函数的参数和返回值类型均为double类型。

对于sqrt()函数,要求输入参数x必须是非负实数。如果x为负数,在大多数实现中会产生域错误(domain error),并返回NaN(Not a Number)值。

现在,我们针对这两个函数与整数之间的关系提出以下两个问题:

  • 1.当n是一个完全平方数时,使用sqrt(n)函数是否能够计算出n的精确整数平方根?
  • 2.使用pow()函数是否能够计算出x^y的精确整数值?
  • 注:本文中所讨论的"整数"一般是指在标准整数类型可表示范围内的整数值。

1. 使用sqrt()是否可以得到完全平方数的精确的整数平方根

1.1 完全平方数的计算结果是否精确?

完全平方数的平方根是整数(例如 sqrt(4)=2)。对于较小的完全平方数(如 4, 9, 16 等),双精度浮点数(double)可以精确表示它们的平方根,因此 sqrt() 函数会返回准确的整数值(如 2.0)。

1.2 为什么不会出现误差(如 1.9999999)?

  • 浮点数的特性
    双精度浮点数(double)的尾数有52位,可以精确表示所有绝对值小于 2^53(约 9e15)的整数。因此,对于较小的完全平方数(如 4, 100, 10000 等),其平方根是整数且落在 2^53 范围内,sqrt() 的结果会是精确的。

  • 数学库的优化
    现代数学库(如 glibc)会对完全平方数的计算进行优化,直接返回精确的整数值,避免浮点运算的舍入误差。

1.3 可能产生误差的情况

只有当完全平方数的平方根 超过双精度浮点数的精确表示范围 时,才会出现误差。例如:

  • 对于 n = (2^26)^2 = 2^52,其平方根 2^26 是精确的。
  • 但对于 n = (2^26 + 1)^2,平方根 2^26 + 1 可能会因超出 2^53 的精确表示范围而产生微小误差。
  • 注:在实测中,没有产生误差,都能精确表示。

1.4 总结

  • 对于较小的完全平方数(如 4, 9, 100 等):
    sqrt() 返回的结果是精确的(如 2.0, 3.0, 10.0),不会出现 1.99999992.00000000001

  • 对于极大的完全平方数(超过 2^53):
    可能因浮点数精度限制产生微小误差,需谨慎处理。


2. 使用pow函数计算整数的幂能否得到精确的整数值

在C语言中,pow函数不能保证总是返回精确的整数值,其准确性取决于以下关键因素:

2.1 浮点数的精度限制

  • pow函数的参数和返回值均为double类型,其底层使用浮点数运算。虽然double类型可以精确表示一定范围内的整数(通常到2⁵³),但当计算结果超出此范围时,精度丢失可能导致误差
  • 示例
    printf("%.0f", pow(2, 53));   //输出 9007199254740992(精确)
    printf("%.0f", pow(2, 53)+1); //同样输出 9007199254740992(无法区分)
    

2.2 隐式类型转换的陷阱

  • 即使输入的底数和指数是整数,pow内部仍会转换为浮点数计算。对于某些看似简单的运算,舍入误差可能导致意外结果
    int a = (int)pow(5, 3);  // 期望125,实际可能得到124(如4.999999被截断)
    

2.3 实现依赖性问题

  • 不同编译器/数学库对pow的优化策略不同。例如:
    pow(10, 2);  // 可能返回100.0(精确)或99.99999999999999(误差)
    

2.4 建议:如何安全计算整数幂?

  1. 小整数幂:直接使用循环乘法

    int power(int base, int exp) {int result = 1;for (int i = 0; i < exp; i++) result *= base;return result;
    }
    
  2. 大整数或高精度需求:使用<stdint.h>中的大整数类型(如int64_t)或第三方库(如GMP)。

  3. 必须用pow:添加误差补偿

    #include <math.h>
    int safe_pow(int base, int exp) {double result = pow(base, exp);return (int)(result + 0.5);  // 四舍五入补偿
    }
    

2.5 结论

  • 可用场景:当结果远小于2⁵³且无需强制转换为整数时,pow可临时使用。
  • 风险场景:涉及大整数、类型转换或高精度需求时,必须避免依赖pow函数。

3. 举例

下列程序在Dev C++环境下运行

#include <stdio.h>
#include <math.h>
int main( void ) {printf("sqrt(): %s %d\n","error.", sqrt(pow(2, 52)));printf("sqrt(): %d %s\n", (int)sqrt(pow(2, 52)), "精确");printf("sqrt(): %d %s\n",(int)sqrt(pow(2, 54)), "精确");long long lnum = sqrt(pow(2, 80));printf("sqrt(): %lld %s\n",lnum, "精确");printf("pow(): %.0f %s\n", pow(2, 53)-1, "精确");printf("pow(): %.0f %s\n", pow(2, 53), "精确");printf("pow(): %.0f %s\n", pow(2, 53)+1, "无法区分");printf("pow(): %.0f %s\n", pow(2, 54), "精确");printf("pow(): %.0f %s\n", pow(2, 55), "精确");printf("pow(): %.0f %s\n", pow(2, 56), "精确");printf("pow(): %.0f %s\n", pow(2, 57), "不精确");printf("pow(): %.0f %s\n", pow(2, 64), "不精确");return 0;
}

运行结果截图如下:
在这里插入图片描述

下列程序在LLVM (clang-cl)环境下运行

#include <stdio.h>
#include <math.h>int main(void) { printf("sqrt(): %s %d\n", "error.", sqrt(pow(2, 52)));printf("sqrt(): %d %s\n", (int)sqrt(pow(2, 52)), "精确");printf("sqrt(): %d %s\n", (int)sqrt(pow(2, 54)), "精确");long long lnum = sqrt(pow(2, 80));printf("sqrt(): %lld %s\n", lnum, "精确");printf("pow(): %.0f %s\n", pow(2, 53) - 1, "精确");printf("pow(): %.0f %s\n", pow(2, 53), "精确");printf("pow(): %.0f %s\n", pow(2, 53) + 1, "无法区分");printf("pow(): %.0f %s\n", pow(2, 54), "精确");printf("pow(): %.0f %s\n", pow(2, 55), "精确");printf("pow(): %.0f %s\n", pow(2, 56), "精确");printf("pow(): %.0f %s\n", pow(2, 57), "精确");printf("pow(): %.0f %s\n", pow(2, 64), "精确");return 0;
}

运行结果截图如下:
在这里插入图片描述

相关文章:

C语言基本概念————讨论sqrt()和pow()函数与整数的关系

本文来源&#xff1a;C语言基本概念——讨论sqrt()和pow()函数与整数的关系. C语言基本概念——sqrt和pow函数与整数的关系 1. 使用sqrt()是否可以得到完全平方数的精确的整数平方根1.1 完全平方数的计算结果是否精确&#xff1f;1.2 为什么不会出现误差&#xff08;如 1.99999…...

【时时三省】(C语言基础)什么是算法

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 一个程序主要包括以下两方面的信息&#xff1a; &#xff08;1&#xff09;对数据的描述。在程序中&#xff0c;要指定用到哪些数据&#xff0c;以及这些数据的类型和数据组织形式。这就是数…...

Spring Boot 中加载多个 YAML 配置文件

在 Spring Boot 中加载多个 YAML 配置文件是一个常见的需求&#xff0c;通常用于将配置信息分离到多个文件中以便于管理和维护。Spring Boot 提供了灵活的方式来加载多个 YAML 配置文件。 以下是一些方法和步骤&#xff0c;用于在 Spring Boot 应用中加载多个 YAML 配置文件&a…...

IPoIB模块初始化过程详解

在现代网络环境中,InfiniBand over IP (IPoIB) 作为一种高性能的网络技术,被广泛应用于数据中心和高性能计算领域。为了确保其稳定性和高效性,Linux内核中的IPoIB模块在加载时需要进行一系列复杂的初始化操作。本文将基于一系列技术对话内容,详细介绍IPoIB模块的初始化流程…...

C语言——排序(冒泡,选择,插入)

基本概念 排序是对数据进行处理的常见操作&#xff0c;即将数据按某字段规律排列。字段是数据节点的一个属性&#xff0c;比如学生信息中的学号、分数等&#xff0c;可针对这些字段进行排序。同时&#xff0c;排序算法有稳定性之分&#xff0c;若两个待排序字段一致的数据在排序…...

如何本地部署DeepSeek

第一步&#xff1a;安装ollama https://ollama.com/download 打开官网&#xff0c;选择对应版本 第二步&#xff1a;选择合适的模型 https://ollama.com/ 模型名称中的 1.5B、7B、8B 等数字代表模型的参数量&#xff08;Parameters&#xff09;&#xff0c;其中 B 是英文 B…...

Docker 部署 MySQL-5.7 单机版

一、镜像获取 # docker hub 镜像 docker pull farerboy/mysql:5.7 # 国内阿里镜像 docker pull registry.cn-hangzhou.aliyuncs.com/farerboy/mysql:5.7 以上两个镜像二选一即可 二、运行容器 docker run -dti --name mysql \n --privileged \n --cgroupns private \n --e…...

正则表达式--元字符-限定符(4)

正则的限定元字符 表示前边一个符号代表的内容出现多少次 1.* ------ 表示0~正无穷次 2. ------ 表示 1~正无穷次 3. ? ------ 表示 0~1次 4. {n} ------ 表示 限定 n 次, 不能多也不能少 5. {n,} ------ 表示 最少 n 次 6. {n,m} ------ 表示 最少 n 次, 最多 m 次 <!DO…...

【CMAEL多智能体框架】第一节 环境搭建及简单应用(构建一个鲜花选购智能体)

第一节 环境搭建 文章目录 第一节 环境搭建前言一、安装二、获取API1. 使用熟悉的API代理平台2.设置不使用明文存放API 三 、具体应用进阶任务 总结 前言 CAMEL Multi-Agent是一个开源的、灵活的框架&#xff0c;它提供了一套完整的工具和库&#xff0c;用于构建和模拟多智能体…...

网络工程师 (31)VLAN

前言 VLAN&#xff08;Virtual Local Area Network&#xff09;即虚拟局域网&#xff0c;是一种将物理局域网划分成多个逻辑上独立的虚拟网络的技术。 一、定义与特点 定义&#xff1a;VLAN是对连接到的第二层交换机端口的网络用户的逻辑分段&#xff0c;不受网络用户的物理位置…...

C++17 新特性解析

C++17 是 C++ 标准的一个重要更新,它在 C++11/14 的基础上引入了许多新特性,进一步简化了代码编写、提升了性能和类型安全性。以下是 C++17 的主要特性分类介绍: 一、语言核心改进 1. 结构化绑定(Structured Bindings) 允许将元组、结构体或数组的成员直接解包到变量中。…...

泛化、选择、分化

泛化是指记忆联系的“发散”&#xff0c;泛化兴奋的基础是模糊兴奋。记忆联系的“发散”有以下几种种情况&#xff1a; 1、联络区的一原始记忆柱群&#xff08;A1&#xff09;具有直接或间接与其它任意联络区的任意原始记忆柱群建立记忆联系的潜力。也就是说任何两个对象&…...

网络安全架构师怎么考 网络安全 架构

安全通信网络 随着现代技术的不断发展&#xff0c;等级保护对象通常通过网络实现资源共享和数据交互&#xff0c;当大量的设备连成网络后&#xff0c;网络安全成了最为关注的问题。按照“一个中心&#xff0c;三重防御”的纵深防御思想&#xff0c;边界外部通过广域网或城域网…...

Android系统分区概述和编译镜像包理解

1. 分区一&#xff1a;bootloader&#xff1b; 设备启动后&#xff0c;会先进入bootloader程序&#xff0c;这里会通过判断开机时的按键组合&#xff0c;选择启动到哪种模式。相当于电脑的bios 这里主要有Android系统、recovery模式&#xff08;音量上键电源键&#xff09;、f…...

【案例教程】无人机生态环境监测、图像处理与GIS数据分析综合实践技术应用

专题一、无人机航拍基本流程、航线规划与飞行实践 1.无人机行业应用概况 2.无人机遥感监测简介 3.无人机与传感器类型 4.无人机航线规划设计&#xff08;谷歌地球软件的使用&#xff09; 5.无人机飞行软件操作&#xff08;DJI App设置实践视频&#xff09; 6.无人机航拍一…...

depcheck检查node.js项目中未使用和缺失依赖的工具

depcheck检查node.js项目中未使用和缺失依赖的工具 一、安装二、使用方法 depcheck 是一个用于检查 Node.js 项目中未使用依赖项和缺失依赖项的工具。以下为你详细介绍它的相关信息、使用方法和作用。 主要作用: 1.发现未使用的依赖 在项目开发过程中&#xff0c;我们可能会安…...

在 C# 中,处理 Excel 和 PDF 文件的库有很多。以下是一些比较常用的选择

读取 Excel 文件的库 NPOI 用途&#xff1a;可以读取和写入 .xls 和 .xlsx 文件。特点&#xff1a;无需安装 Microsoft Office&#xff0c;支持简单的 Excel 操作&#xff0c;如格式化、公式、图表等。 EPPlus 用途&#xff1a;主要用于 .xlsx 格式&#xff08;Excel 2007 及以…...

HTML之JavaScript函数声明

HTML之JavaScript函数声明 1. function 函数名(){}2. var 函数名 function(){}<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1…...

【算法】动态规划专题⑪ —— 区间DP python

目录 引入进入正题回归经典总结 引入 区间动态规划&#xff08;区间DP&#xff09;适用于解决涉及区间最优化的经典问题&#xff0c;如石子合并、最长回文子序列等。 进入正题 石子合并 https://www.acwing.com/problem/content/284/ 有 N 堆石子排成一排&#xff0c;其编号为…...

现代C++多线程基础 -忆苦思甜pthread_mutex

c 老古董 文章目录 c 老古董pthread_mutex概念常用apipthread_mutex_initpthread_mutex_lockpthread_mutex_trylockpthread_mutex_unlockpthread_mutex_destroy 案例 pthread_mutex 概念 互斥锁 mutex是一种简单的加锁的方法来控制对共享资源的访问&#xff0c;mutex只有两种…...

玩转适配器模式

文章目录 解决方案现实的举例适用场景实现方式适配器模式优缺点优点:缺点:适配器模式可比上一篇的工厂模式好理解多了,工厂模式要具有抽象的思维。这个适配器模式,正如字面意思,就是要去适配某一件物品。 假如你正在开发一款股票市场监测程序, 它会从不同来源下载 XML 格…...

腾讯云大数据套件TBDS与阿里云大数据能力产品对比

前言 博主在接触大数据方向研究的时候是在2016年,那时候正是大数据概念非常火热的一个时间段,最著名的Google的3篇论文。Google FS、MapReduce、BigTable,奠定了大数据框架产品的基础。Google文件系统,计算框架和存储框架。往后所有的大数据产品和过程域无一不是在三个模块…...

Codeforces Round 1003 (Div. 4)(A~G题题解)

A. Skibidus and Amogu 思路&#xff1a;把字符串最后的us变成i就可以了&#xff0c;水题一个 #include <iostream> #include <string> int main() { int t; std::cin >> t; std::cin.ignore(); while (t--) { std::string W; std::getline(std::c…...

ubuntu使用防火墙开放和关闭指定端口

防火墙可以阻止或允许外部对特定端口的访问&#xff0c;Ubuntu 常用的防火墙管理工具是 ufw&#xff08;Uncomplicated Firewall&#xff09; &#xff0c;如果在开发网络通信相关的内容时&#xff0c;要确保所需的端口是打开的&#xff0c;这样可以排除出题出现时的一个问题—…...

CP AUTOSAR标准之GPTDriver(AUTOSAR_SWS_GPTDriver)(更新中……)

1 简介和功能概述 该规范指定了AUTOSAR基础软件模块GPT驱动程序的功能、API和配置。   GPT驱动程序是微控制器抽象层(MCAL)的一部分。它初始化并控制微控制器的内部通用定时器(GPT)。   GPT驱动程序提供服务和配置参数 启动和停止硬件计时器获取计时器值控制时间触发的中断…...

mysql8.0使用PXC实现高可用

1.什么是 PXC PXC 是一套 MySQL 高可用集群解决方案&#xff0c;与传统的基于主从复制模式的集群架构相比 PXC 最突出特点就是解决了诟病已久的数据复制延迟问题&#xff0c;基本上可以达到实时同步。而且节点与节点之间&#xff0c;他们相互的关系是对等的。PXC 最关注的是数据…...

大数据学习之SparkStreaming、PB级百战出行网约车项目一

一.SparkStreaming 163.SparkStreaming概述 Spark Streaming is an extension of the core Spark API that enables scalable, high-throughput, fault-tolerant stream processing of live data streams. Spark Streaming 是核心 Spark API 的扩展&#xff0c;支持实时数据…...

Ollama部署DeepSeek(windows or ubuntu)

Ollama(官网是https://ollama.com/)是一个专为在本地机器上便捷部署和运行大型语言模型&#xff08;LLM&#xff09;而设计的开源框架。它简化了大型语言模型的部署过程&#xff0c;提供了轻量级与可扩展的架构&#xff0c;使得研究人员、开发人员和爱好者能够更加方便地在本地…...

10.代码生成器-树表

1.导入部门表 2.配置生成信息页面 生成代码即可使用。...

2050年10月26日,星期四,芜湖

2050年10月26日&#xff0c;星期四&#xff0c;芜湖 清晨6:30&#xff0c;阳光透过智能调光窗帘缓缓洒进卧室&#xff0c;没有刺耳的闹钟&#xff0c;取而代之的是模拟自然光线和舒缓的江水声&#xff0c;这是林薇一天美好的开始。她的智能手环早已监测到她已进入浅睡眠状态&a…...