[Sword Finger Offer] -implement funciones de biblioteca específicas pow, atoi

En las preguntas de la entrevista, a menudo hay funciones para procesar valores numéricos y cadenas. En este artículo, explicamos principalmente la implementación de una función pow y atoi ~

Uno, función pow

Requisitos de tema

Implemente la función double Power (base doble, exponente int), encuentre la potencia exponente de la base. No use las funciones de la biblioteca y no es necesario tener en cuenta los números grandes.

Análisis de tema

Debido a que no es necesario considerar el problema de los grandes números, en primer lugar, cuando tenemos este problema, la idea que surgió de nuestro cerebro se realiza de la siguiente manera:

double Power(double base, int exponent)
{
	double result = 0;
	for (int i = 0; i <= exponent; i++)
	{
		result *= base;
	}
	return result;
}

Pero escribir así definitivamente está mal. Hay muchas deficiencias

Mejora 1: Considere el caso donde la base es 0 y el exponente es negativo.
Debido a un caso tan especial, debemos considerar la forma de manejo de errores.
En los programas que escribimos, generalmente hay tres métodos de manejo de errores. A continuación se muestran sus ventajas y desventajas correspondientes
Inserte la descripción de la imagen aquí
. El código mejorado es el siguiente:

bool g_InvalidInput = false;

double Power(double base, int exponent)
{
	g_InvalidInput = false;

	if (equal(base, 0.0) && exponent < 0)
	{
		g_InvalidInput = true;
		return 0.0;
	}

	unsigned int absExponent = (unsigned int)(exponent);
	if(exponent < 0)
		absExponent = (unsigned int)(-exponent);

	double result = Powerresult(base, absExponent);
	if (exponent < 0)
		result = 1.0 / result;
	return result;
}		

En nuestro código anterior, usamos variables globales para identificar si algo salió mal. Si algo sale mal, el valor devuelto es 0. Sin embargo, para distinguir si devuelve 0 cuando ocurre un error o vuelve a 0 cuando la base es 0, diseñamos la variable global g_InvalidInput para distinguir. Cuando se produce un error, esta variable se establece en verdadera, de lo contrario es falsa.

Mejora 2: Método Powerresult más eficiente
Si nuestro exponente de entrada es 32, en nuestro bucle anterior, tenemos que hacer 31 bucles, pero si lo pensamos cuidadosamente, parece haber un método más conciso.
Aquí vamos a mencionar una solución que mencionamos en la secuencia de Fibonacci. Hay un método para usar una fórmula matemática en la secuencia de Fibonacci. Su complejidad temporal es O (logn). La fórmula matemática que considera el poder es la siguiente:
Inserte la descripción de la imagen aquí
de la fórmula anterior, podemos ver que queremos mejorar el método n veces Al cuadrado, primero debemos obtener la potencia n / 2, y luego al cuadrado el resultado de la potencia n / 2. Esto se puede lograr con una idea recursiva.
Con el presagio de la secuencia de Fibonacci, es más fácil para nosotros pensar en la función. Porque estamos pidiendo la 32ª potencia, a partir de la cual calculamos la 16ª potencia, la 8ª potencia, la 4ª potencia y el cuadrado. La fórmula matemática derivada de esto es la siguiente: en
Inserte la descripción de la imagen aquí
base a la fórmula anterior, el código se implementa de la siguiente manera:

double Powerresult(double base, unsigned int exponent)
{
	if (exponent == 0)
		return 1;
	if (exponent == 1)
		return base;

	//递归乘法的过程
	double result = Powerresult(base, exponent >> 1);
	result *= result;

	//指数为奇数的情况
	if ((exponent & 0x1) == 1)
		result *= base;

	return result;
}

Dos, función atoi

Requisitos de tema

Convierta la cadena a un entero, por ejemplo, ingrese la cadena "123", su salida es el número 123

Análisis de tema

Primero obtenga esta pregunta, de acuerdo con los requisitos de la pregunta, naturalmente solo pensamos en el caso de convertir "123" en el número 123. Pero esta pregunta no solo es tan simple, sino que también considera una situación así, también tiene muchas situaciones especiales de entrada que deben considerarse en pequeños detalles.

Caso 1 : compruebe si la cadena está vacía

str != nullptr

Caso 2 : cuando la cadena de entrada es "0"

Aquí, cuando la cadena que ingresamos es "0", su valor de retorno debe ser 0, pero entra en conflicto con el retorno de 0 cuando la cadena es una cadena vacía, por lo que debemos establecer una variable global para distinguirla. Si es una entrada ilegal, devuelve 0 y establece la variable global como una marca especial; si la entrada es la cadena "0", devuelve 0 y la variable global no se establecerá.

enum Status{kValid = 0,kInvaild};
int g_nStatus = kValid;

** Caso 3: ** No todos los caracteres que no sean "0" ~ "9" son ilegales, la cadena de entrada tendrá una diferencia entre los signos positivos y negativos, por lo que los signos más y menos también deben ser de entrada legal

if (*str == '+')
   str++;
else if (*str == '-')
{
	str++;
	minus = true;
}

Caso 4 : considere el caso donde el valor entero positivo más grande es 0x7FFFFFFF y el valor entero negativo más pequeño es 0x80000000

La implementación completa del código es la siguiente:
dividimos dos funciones para implementar específicamente la función StrToInt principalmente para determinar si es una entrada legal, StrToIntCore es el código central para la conversión específica

enum Status{kValid = 0,kInvaild};
int g_nStatus = kValid;
long long StrToIntCore(const char* digit, bool minus);

int StrToInt(const char* str)
{
	g_nStatus = kInvaild;
	long long num = 0;

	if (str != nullptr && *str != '\0')//空串判断
	{
		bool minus = false;//设置一个布尔值来保存符号
		//符号判断
		if (*str == '+')
			str++;
		else if (*str == '-')
		{
			str++;
			minus = true;
		}

		//其余字符串转换
		if (*str != '\0')
		{
			num = StrToIntCore(str, minus);
		}
	}
	return (int)num;
}
long long StrToIntCore(const char* digit, bool minus)
{
	long long num = 0;

	while (*digit != '\0')
	{
		if (*digit >= '0' && *digit <= '9')
		{
			int flag = minus ? -1 : 1;
			num = num * 10 + flag * (*digit - '0');//核心代码

			//溢出判断
			if ((!minus && num > 0x7FFFFFFF) || (minus && num < (signed int)0x80000000))
			{
				num = 0;
				break;
			}
			digit++;
		}
		else//非法输入
		{
			num = 0;
			break;
		}
	}
	//输入为'\0'的合法情况
	if (*digit == '\0')
	{
		g_nStatus = kValid;
	}
	return num;
}
Publicado 98 artículos originales · ganado elogios 9 · vistas 3649

Supongo que te gusta

Origin blog.csdn.net/qq_43412060/article/details/105403765
Recomendado
Clasificación