重写重要的库函数

重写幂次函数

pow(double base, int exp);

首先要写一些测试用例:

1.base=0时,exp<=0是不合法的输入。
2.base不等于0,exp<0时,要计算的值是base的|exp|次幂,然后取倒数。
3.base不等于0,exp>0时,直接计算base的|exp|次幂。

代码实现:

double myPow(double x, int n)
{
	if(equalZero(x, 0.0) && n <= 0)
	{
		return 0.0;
	}

	int absExp = n;
	if(n < 0)
	{
		absExp = -n;
	}

	double res = getPowWithAbsExp(x, absExp);

	if(n < 0)
		res = 1.0 / res;

	return res;
}

double getPowWithAbsExp(double base, int absExp)
{
	double result = 1.0;
	for(int i = 0; i < absExp; ++i)
	{
		result *= base;
	}

	return result;
}

bool equalZero(double num1, double num2)
{
	double delt = 0.0001;
	if((num1 - num2 < delt) && (num1 - num2 > -delt))
	{
		return true;
	}
	else
	{
		return false;
	}
}//equalZero()

  但是这时新的问题来了,如果exp很大,那么这个样子的连乘,肯定需要很大的时间复杂度。这里利用到了归并排序的思想,把相同的小的子问题,配对计算,得出中等的问题,然后再把中等的问题配对计算,最后得到大的问题的解。这一点很像合并K个有序的链表中用到的方法。

所以新的getPowWithAbsExp函数可以这样写:

double getPowWithAbsExp(double base, int absExp)
{
	double result = 0.0;
	if(absExp == 0)
		return 1.0;
	if(absExp == 1)
		return base;

	result = getPowWithAbsExp(base, absExp / 2);
	result *= result;

	if(absExp % 2 != 0)
		result *= base;

	return result;
}

  这样就通过归并的方法,大大的减少了计算乘法的次数

重写memmove函数

在内存复制的时候,如果两段内存有重叠,那么就很容易产生覆盖。所以重写这个函数,对有重叠的内存的拷贝进行处理。

void* memmove(void* str1,const void* str2,int n)
{
    char* pStr1 = (char*) str1;
    const char* pStr2 = (const char*)str2;

    if(pStr1 < pStr2)	//从前面开始copy
	{
        for(int i=0; i!=n; ++i)
		{
            *(pStr1++) = *(pStr2++);
        }
    }
    else	//从后面开始copy
	{
        pStr1 += n-1;
        pStr2 += n-1;
        for(int i=0; i!=n; ++i)
		{
            *(pStr1--) = *(pStr2--);
        }
    }

    return pStr1;
}

  为了避免把还未copy的内存区域覆盖掉,这里用到的解决办法就是根据两块内存的位置,从前面或者后面进行内存copy。

时间: 2024-10-11 20:05:25

重写重要的库函数的相关文章

【转】stm32CubeMx上移植自己的printf()和scanf()函数

要想printf()和scanf() 函数工作,我们需要把printf()和scanf() 重新定向到串口中.重定向是指用户可以自己重写C 的库函数,当连接器检查到用户编写了与C 库函数相同名字的函数时,优先采用用户编写的函数,这样用户就可以实现对库的修改了.为了实现重定向printf()和scanf() 函数,我们需要分别重写fputc()和fgetc() 这两个C 标准库函数. 一.移植printf()函数,重定向C库函数printf到USART1 int fputc(int ch, FIL

蒟蒻的代码规范与文档编写规范

代码规范 代码每行不得超过 80 个字符: 代码不分块.连续编写,且每一个模块不允许超过 100 行: 双目运算符运算对象与运算符之间一定要分别打一个空格,单目运算符与运算对象之间不打空格: 禁止使用 Tab 缩进,使用 2 空格缩进代码. 宏定义时没有缩进. 基本使用 Java 代码风格,如果在 for.if 后只有一两个语句,尽量不使用大括号包围,如果一定要使用大括号,则尽量压行书写. 模块化的代码,提倡代码宽而短,不提倡瘦长的代码风格. 没有通用的头文件,随用随加. 尽量开局部变量,减少全

JavaScript垃圾回收机制

原文地址:https://www.cnblogs.com/zhwl/p/4664604.html 一.垃圾回收的必要性 下面这段话引自<JavaScript权威指南(第四版)> 由于字符串.对象和数组没有固定大小,所有当他们的大小已知时,才能对他们进行动态的存储分配.JavaScript程序每次创建字符串.数组或对象时,解释器都必须分配内存来存储那个实体.只要像这样动态地分配了内存,最终都要释放这些内存以便他们能够被再用,否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系

[重写库函数]atoi

1. 若字符串开头是空格,则跳过所有空格,到第一个非空格字符,如果没有,则返回0. 2. 若第一个非空格字符是符号+/-,则标记isPositive的真假,这道题还有个局限性,那就是在c++里面,+-1和-+1都是认可的,都是-1,而在此题里,则会返回0. 3. 若下一个字符不是数字,则返回0. 完全不考虑小数点和自然数的情况,不过这样也好,起码省事了不少. 4. 如果下一个字符是数字,则转为整形存下来,若接下来再有非数字出现,则返回目前的结果. 5. 还需要考虑边界问题,如果超过了整形数的范围

linux内核系统调用和标准C库函数的关系分析

今天研究了一下系统调用和标准库函数的区别和联系,从网上搜集的资料如下: 1.系统调用是为了方便应用使用操作系统的接口,而库函数是为了方便人们编写应用程序而引出的,比如你自己编写一个函数其实也可以说就是一个库函数. 2.系统调用可以理解为内核提供给我们在用户态用的接口函数,可以认为是某种内核的库函数. 3.read就是系统调用,而fread就是C标准库函数. 4.很多c函数库中的函数名与系统调用的名称一样是因为该函数本身其实就是调用的系统调用,放到c函数库就是为了用户态的使用 5.写程序直接使用的

C++常用库函数

C++常用库函数  转自:http://blog.csdn.net/sai19841003/article/details/7957115 1.常用数学函数 头文件 #include <math> 或者 #include <math.h>   函数原型 功能 返回值 int abs(int x) 求整数x的绝对值 绝对值 double acos(double x) 计算arcos(x)的值 计算结果 double asin(double x) 计算arsin(x)的值 计算结果 d

C++库函数大全

C++常用库函数   1.常用数学函数 头文件 #include <math> 或者 #include <math.h>   函数原型 功能 返回值 int abs(int x) 求整数x的绝对值 绝对值 double acos(double x) 计算arcos(x)的值 计算结果 double asin(double x) 计算arsin(x)的值 计算结果 double atan(double x) 计算arctan(x)的值 计算结果 double cos(double x

C语言库函数大全及应用实例二

原文:C语言库函数大全及应用实例二                                              [编程资料]C语言库函数大全及应用实例二 函数名: bioskey 功 能: 直接使用BIOS服务的键盘接口 用 法: int bioskey(int cmd); 程序例: #i nclude #i nclude #i nclude #define RIGHT 0x01 #define LEFT 0x02 #define CTRL 0x04 #define ALT 0x0

面试-重写基础功能函数

重写基础函数 1. 字符串拷:strcpy() 函数strcpy的原型是char* strcpy(char* des , const char* src),des 和 src 所指内存区域不可以重叠且 des 必须有足够的空间来容纳 src 的字符串. char* strcpy( char* dst, const char* src ) { assert( NULL != dst && NULL != src ); char* rtn = dst; while ( (*dst++ = *s