剑指offer-11-数值的整数次方

2023-11-03

0、问题

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

保证base和exponent不同时为0

1、一般思路

把情况考虑完整: 2 − 5 2^{-5} 25, 2 0 2^0 20, 2 5 2^{5} 25
同时,直接进行相乘,也能计算出来,此时未考虑优化问题。

判断double是否相同的方法:equal

const double  min_value = 1e-7;
bool equal(double num1, double num2)
  {
      if(num1 - num2 < - min_value || num1 - num2 > min_value)
      {
          return false;
      }
      else
      {
          return true;
      }
  }

equal的另一种实现方法:

int equal(double left, double right)
{
    if((left - right) < min_value && (left - right) > -min_value)
        return true;
    else 
        return false;
}

只有在下面两个范围内,超过了浮点数表示精度,才认为两个相等,所以这里是 && 符号(易错)。
在这里插入图片描述

将最常见的几种情况考虑完整,依次相乘,可得出下面代码。

double Power(double base, int exponent) 
{
   if (equal(base, 0.0) && exponent <= 0)
         return 0; //这里已经输入不合法了

     bool flag_positive = true;
     if (exponent < 0)
     {
         flag_positive = false;
         exponent = -exponent;
     }
     else if (exponent == 0)
     {
         return 1;
     }

     double ret = 1.0;
     for (size_t i = 0; i < exponent; i++)
     {
         ret *= base;
     }

     if (!flag_positive)
         ret = 1.0 / ret;

     return ret;
}

上述代码,思路比较直观,但仔细分析会发现,中间有可以优化的地方。

2、最优方法 – 快速求幂算法

如果指数为32,我们在循环中做31次乘法。换个角度,我们知道了16次方,直接在16次方的基础上平方就可以获知到32次方的值。而16是8次方的值,以此类推,求32次方,只需要做5次乘法:先平方,平方的基础上求得4次方,4次方的基础上求得8次方,8的基础上求得16,16的基础上求得32.

其实上述思路就是 【快速求幂算法】,算法思路可以参考原文,算法伪代码为:

POWER_INTEGER(x, n)
1 pow ← 1
2 while (n > 0)
3     do if (n mod 2 = 1)
4            then pow ← pow * x
5       x ← x * x
6       n ← n / 2
7 return pow

实现代码见完整代码中Power_quick 部分。

注意:

  1. 最开始对while中的if (exponent & 0x1)语句理解错误,需要注意。
  2. 编译器的警告信息不能忽略,都要看一下。下面两条在编译器中都提示了,最开始没忽视了。。。
    • 最开始把Min_value定义在Solution类中
    • if (exponent & 0x1 == 1),其中 ==的优先级更高,然后才是 &

3、完整代码:

#include <iostream>
#include <cstdlib>
#include <ctime>

const double Min_value = 1.0e-7;

class Solution
{
    bool equal(double num1, double num2)
    {
        if (num1 - num2 < -Min_value || num1 - num2 > Min_value)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

public:
	//快幂法
    double Power_quick(double base, int exponent)
    {
        if (equal(base, 0.0) && exponent <= 0)
            return 0;

        bool flag_positive = true;
        if (exponent < 0)
        {
            flag_positive = false;
            exponent = -exponent;
        }
        else if (exponent == 0)
        {
            return 1;
        }

        double ret = 1.0;
        int tmp = exponent;
        while (exponent > 0)
        {
            //如果是奇数,需要再继续乘 base,下面类似于取余(%)操作行,需要放在外面
            if (exponent & 0x1) //n & 1 等价于 (n % 2) == 1
            {
                ret *= base;
                // printf("1.ret: %d, exponent = %d, base = %.2lf\n", exponent & 0x1, exponent, base);
            }

            base *= base;
            exponent >>= 1;  n >>= 1 等价于 n /= 2
        }
        
        if (!flag_positive)
            ret = 1.0 / ret;

        return ret;
    }

	//依次乘
    double Power_order(double base, int exponent)
    {
        if (equal(base, 0.0) && exponent <= 0)
            return 0;

        bool flag_positive = true;
        if (exponent < 0)
        {
            flag_positive = false;
            exponent = -exponent;
        }
        else if (exponent == 0)
        {
            return 1;
        }

        double ret = 1.0;
        for (size_t i = 0; i < exponent; i++)
        {
            ret *= base;
        }

        if (!flag_positive)
            ret = 1.0 / ret;

        return ret;
    }
};

int main()
{
    Solution ans;

    int start_time = clock();
    double ret = ans.Power_quick(5, 10);
    printf("value: %.2lf, time: %lu\n", ret, clock() - start_time);

    start_time = clock();
    ret = ans.Power_quick(5, 11);
    printf("value: %.2lf, time: %lu\n", ret, clock() - start_time);

    start_time = clock();
    ret = ans.Power_order(5, 10);
    printf("value: %.2lf, time: %lu\n", ret, clock() - start_time);

    start_time = clock();
    ret = ans.Power_order(5, 11);
    printf("value: %.2lf, time: %lu\n", ret, clock() - start_time);

    ///
    start_time = clock();
    ret = ans.Power_quick(5, 30);
    printf("value: %.2lf, time: %lu\n", ret, clock() - start_time);

    start_time = clock();
    ret = ans.Power_quick(5, 31);
    printf("value: %.2lf, time: %lu\n", ret, clock() - start_time);

    start_time = clock();
    ret = ans.Power_order(5, 30);
    printf("value: %.2lf, time: %lu\n", ret, clock() - start_time);

    start_time = clock();
    ret = ans.Power_order(5, 31);
    printf("value: %.2lf, time: %lu\n", ret, clock() - start_time);
}

测试了一下时间,上面几个时间差不多,暂不知道是什么原因。
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

剑指offer-11-数值的整数次方 的相关文章

  • [c++] 大整数乘法(字符串乘法)

    include
  • 645.错误的集合(力扣leetcode) 博主可答疑该问题

    一 笔记部分 思路 1 可以用排序 先排序后连续两个相同 还有那个位置上缺了就是那个 2 转化为负数 先遍历一次先将每个元素所对应位置的树转化为负数 然后再遍历一次看那个是负数 就是出现了两次 再看索引的数字是否为负数 因为出现了的都是为负
  • leetcode刷题(二)

    题目一 题目链接 void reverse int arr int left int right while left
  • 【C语言刷题】将一个十进制数字转化为二进制数字

    题目描述 将一个十进制的数字转化为二进制的数字 测试用例 输入 10 输出 1010 输入 9 输出 1001 思路 可以发现二进制位是满2进1 则可以通过 2来判断是否需要进位 依次作为循环终止条件 通过 2可以判断二进制的每一位对应的数
  • 合并两个有序数组(C语言)

    让我们来看一下这道题的描述 题目描述 题目 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2 另有两个整数 m 和 n 分别表示 nums1 和 nums2 中的元素数目 请你合并 nums2 到 nums1 中 使合并后
  • 动态规划 - 切钢条 (python)

    博主在读 算法导论 时 看到了切钢条的自底向上的伪代码 就分享给大家 BOTTOM UP CUT ROD p n 1 let r 0 n be a new array 2 r 0 0 3 for j 1 to n 4 q 负无穷 5 for
  • 【HDLBits 刷题 12】Circuits(8)Finite State Manchines 27-34

    目录 写在前面 Finite State Manchines 2014 q3c m2014 q6b m2014 q6c m2014 q6 2012 q2fsm 2012 q2b 2013 q2afsm 2013 q2bfsm 写在前面 HD
  • 贪心算法力扣刷题练习(含思路与题解)

    贪心算法 保证每次操作都是局部最优 使得最终结果也是全局最优的 需要找到贪心的策略 使得每次的最优能保证全局最优 通常需要排序 根据排序需求 自定义比较函数 sort a begin a end vector
  • Python中heapq模块浅析

    Python提供了heapq模块 有利于我们更好的对堆的相关操作进行简化 下面总结我所用到的相关方法 文章目录 0 回顾堆的概念 1 heappush heap item 建立大 小根堆 2 heapify heap 建立大 小根堆 3 h
  • 二叉树(构造篇)

    二叉树 纲领篇 先复述一下前文总结的二叉树解题总纲 是否可以通过遍历一遍二叉树得到答案 如果可以 用一个 traverse 函数配合外部变量来实现 这叫 遍历 的思维模式 是否可以定义一个递归函数 通过子问题 子树 的答案推导出原问题的答案
  • 【java筑基】IO流基础之文件的常见操作

    前 言 作者简介 半旧518 长跑型选手 立志坚持写10年博客 专注于java后端 专栏简介 深入 全面 系统的介绍java的基础知识 文章简介 本文将深入全面介绍IO流知识 建议收藏备用 创作不易 敬请三连哦 大厂真题 大厂面试真题大全
  • 【C语言】杨氏矩阵

    题目描述 有一个数字矩阵 矩阵的每行从左到右是递增的 矩阵从上到下是递增的 请编写程序在这样的矩阵中查找某个数字是否存在 要求 时间复杂度小于O N 思路1 可以采用遍历方式一个个查找 但是这样时间复杂度为O N 不满足题目要求 思路2 先
  • 数据结构——链表练习题

    题目一 思路 双指针 当listA和listB其中一个位空时 两个列表就不存在相交 返回NULL 当listA和listB都不为空链表时 指针phead1和phead2同时分别遍历listA和listB 遍历完后 再去分别遍历listB和l
  • leecode刷题笔记-数组

    数组题注意事项 1 切记while循环的循环条件一定要判断遍历长度是否越界且要先判断该条件 否则就会报错 例如 while j
  • LeetCode 每日一题 2022_list

    网页链接 LeetCode 坚持住 小镁铝 2022年1月每日一题记录
  • 树的一些基础概念、堆和 python中heapq模块使用简介

    树定义 树是一种数据结构 比如 目录结构 树是由n个节点组成的集合 n 0 那么是一颗空树 n gt 0 那么存在一个节点为书的根节点 其他节点可分为m个子集 每个子集又为一棵子树 关于树的一些概念 根节点 例 A 叶子节点 不能分叉的节点
  • 动态规划(上)

    题目一 109 数字三角形 LintCode 分治 利用递归可以很快的写出程序 class Solution public int traverse vector
  • 2022芯原芯片设计 笔试题分析和讨论

    2022芯原设计笔试题分析和讨论 以下仅为个人理解和分析 不保证正确 欢迎大家发表自己的想法 讨论出正确答案 企业知识题 1 1 D 芯原的主要经营模式为芯片设计平台即服务 Silicon Platform as a Service SiP
  • 跟着英雄刷算法-素数

    跟着英雄大佬刷算法的第三天 数论基础 优化一 对于一个非素数n来说 如果x是n的一个因子 那么n x也是n的一个因子 我们可以假设x 所以对于一个数n 判断它是否为一个素数我们需要确定的范围为 2 根号下n 优化二 例1 不是素数返回0 b
  • 链表【1】

    文章目录 2 两数相加 1 题目 2 算法原理 3 代码实现 445 两数相加 II

随机推荐

  • 计算二叉树的深度和叶子结点数(递归算法实现)

    问题描述 计算二叉树的深度和叶子结点数 输入形式 输入二叉树的先序遍历序列建立二叉树 输出形式 输出二叉树的叶子结点数和深度 样例输入 A B C 样例输出 Leaves 1 Depth 3 求给定二叉树的深度 二叉树的深度就是二叉树中结点
  • 软件测试的八股文内容

    软件测试理论基础 1 软件测试概念 软件测试的定义 在规定的条件下对软件进行操作 以发现错误 对软件质量进行评估 软件测试的范围 对软件形成中的文档 数据及程序进行测试 而不仅仅对程序进行测试 2 软件测试的目的 测试的目的不仅仅是为了发现
  • WebClient学习

    1 介绍 Java中传统的RestTemplate 的主要问题在于不支持响应式流规范 也就无法提供非阻塞式的流式操作 而WebClient是响应式 非阻塞的客户端 属于Spring5中的spring webflux库 2 依赖 maven依
  • 一般熟练盲打需要多久_学会盲打要多长时间,每天要练多长时间 盲打要练多久...

    1 注意自己打字的姿势 第一步要做到背挺直 眼睛离键盘大约半米左右 这是为了让整个都在视野里 双手食指自然的放在 F 和 J 键上 2 熟悉键盘的键位 注意打字时不要只用一个手指去打 一定要让每个手指都有分工 3 手指的正确位置 注意手指的
  • 浅谈C++值传递、地址传递、引用传递

    浅谈C 值传递 地址传递 引用传递 共同的困惑 函数 形式参数和实体参数 值传递 数组作为参数时除外 地址传递 引用传递 作者 Gl Zhang96 来源 CSDN 版权声明 本文为博主原创文章 转载请附上博文链接 共同的困惑 相信大家在入
  • 对于程序员来说,有哪些适合的副业可以选择?

    程序员应该如何选择副业 做副业要满足几个条件 首先是有时间 能让你有精力投入到副业中去 除去这个先决条件 程序员在选择副业的时候可以从这3个方向去思考 方向一 技能 业务 比如技术顾问 培训老师 APP开发等等 方向二 资源 业务 比如字节
  • 组合数学之递推关系(一)定义及几个经典例子

    说明 本文参考了组合数学课件 精简整理了一下内容并谈谈自己的理解 定义 设 an a n a n 为一序列 把该序列中 an a n a n和它前面几个 ai a i a i
  • CCF-CSP 201412-2【Z字形扫描】一种自定义排序的做法

    问题描述 在图像编码的算法中 需要将一个给定的方形矩阵进行Z字形扫描 Zigzag Scan 给定一个n n的矩阵 Z字形扫描的过程如下图所示 对于下面的4 4的矩阵 1 5 3 9 3 7 5 6 9 4 6 4 7 3 1 3 对其进行
  • Android_studio项目文件结构分析

    不得不说 Android studio比ecplise功能要强大 一些小问题的解决也方便很多 今天记录一波android studio 项目文件结构分析 源于网络 本人只是学习 首先搞清楚AS项目结构是由三种视图的 就是这几个啦 Proje
  • H5使用微信和支付宝支付

    项目需求 App中要使用H5的支付宝或者微信支付 官方是不推荐这样使用的 微信支付 首先请求后台的下单接口 接口会返回一个可以跳转的URL地址 https wx tenpay com cgi bin mmpayweb bin checkmw
  • a元素使用

    a元素 超链接元素 href属性中指定的网址如果不是以https或者http开头的 那么都是一个相对网址 他的绝对路径目录是当前网址的绝对路径的目录部分 href hyper 超级的 reference 引用 跳转地址 他可以跳转如下几个位
  • wireshark过滤器的使用

    玉兰花 安全小白成长笔记 1 wireshark过滤器的使用 文章目录 玉兰花 安全小白成长笔记 1 前言 一 什么是wireshark过滤器 二 过滤器的使用 1 按照协议过滤 2 按照IP地址过滤 3 按照端口过滤 3 按关键字过滤 4
  • 如何干掉腾讯网迷你版

    如何干掉腾讯QQ弹窗 腾讯网迷你版 最近在微软商店下载了MS版的QQ for Windows 旨在避免国内官网版本捆绑的Qprotect Q盾 扫盘流氓进程 没想到扫盘进程没了 多了一个广告弹窗服务 网上有人提到这个 腾讯网迷你版 可以在Q
  • 深度学习训练中迭代次数对最后预测结果的影响

    深度学习训练中迭代次数对最后预测结果的影响 代码的运行环境 源代码 控制迭代次数 代码的运行环境 win10专业版 Anaconda2020 02 tensorflow1 14 0 keras2 2 5 源代码 源代码主要来自杨培文的 深度
  • 机器学习 day19(使用python和np实现前向传播)

    1 烤咖啡豆模型 使用一维数组来表示这些向量和参数 所以只有一个方括号 W1 1 表示layer 1的第一个神经元的W Z1 1 表示 W1 1和输入X之间的点积 再与b1 1相加 a1 1 表示应用Z1 1的sigmoid函数 a1 表示
  • 剪映专业版 for Mac(全能易用的剪辑软件)v2.3

    剪映专业版 for Mac 界面更清晰 面板更强大 布局更适合电脑端用户 适用更多专业剪辑场景 延续剪映移动端全能易用的风格 无论你是剪辑师 学生 vlogger 剪辑爱好者 博主 都能够迅速上手操作 制作更专业 更高阶的视频效果 元宇宙
  • error LNK2005: _DllMain@12 已经在 dllmain.obj 中定义

    error LNK2005 DllMain 12 已经在 dllmain obj 中定义 今天遇到了同样的问题 搜索搜到了这里 后来解决了 创建解决方案时 用的是WIN32 DLL 添加了MFC ATL的支持 自动生成文件中是没有现成的Dl
  • RMPE: Regional Multi-person Pose Estimation 论文解读

    paper title RMPE Regional Multi person Pose Estimation paper link https arxiv org pdf 1612 00137 pdf project https www m
  • ubuntu18 Swin-Transformer-Object-Detection

    1 目标检测 https github com SwinTransformer Swin Transformer Object Detection 原文地址 https arxiv org abs 2103 14030 代码地址 https
  • 剑指offer-11-数值的整数次方

    文章目录 0 问题 1 一般思路 2 最优方法 快速求幂算法 3 完整代码 0 问题 给定一个double类型的浮点数base和int类型的整数exponent 求base的exponent次方 保证base和exponent不同时为0 1