c++ - resueltos - ¿Cómo obtener los dígitos de un número sin convertirlo en una matriz de cadena/char?
leer cadena de caracteres en c (14)
¿Qué pasa con el floor(log(number))+1
?
Con n dígitos y utilizando la base b puede expresar cualquier número hasta pow(b,n)-1
. Entonces, para obtener el número de dígitos de un número x en la base b puede usar la función inversa de exponenciación: logaritmo base-b. Para tratar con resultados no enteros, puede utilizar el truco floor()+1
.
PD: esto funciona para enteros, no para números con decimales (en ese caso, debe saber cuál es la precisión del tipo que está usando).
¿Cómo obtengo los dígitos de un número en C ++ sin convertirlo en cadenas o matrices de caracteres?
¿Quieres algo así?
int n = 0;
std::cin>>n;
std::deque<int> digits;
if(n == 0)
{
digits.push_front(0);
return 0;
}
n = abs(n);
while(n > 0)
{
digits.push_front( n % 10);
n = n /10;
}
return 0;
Algo como esto:
int* GetDigits(int num, int * array, int len) {
for (int i = 0; i < len && num != 0; i++) {
array[i] = num % 10;
num /= 10;
}
}
El mod 10 te dará los dígitos. Los div 10s avanzarán el número.
Esas soluciones son todas recursivas o iterativas. ¿Podría un enfoque más directo ser un poco más eficiente?
De izquierda a derecha:
int getDigit(int from, int index)
{
return (from / (int)pow(10, floor(log10(from)) - index)) % 10;
}
De derecha a izquierda:
int getDigit(int from, int index)
{
return (from / pow(10, index)) % 10;
}
Hace años, en respuesta a las preguntas anteriores, escribiría el siguiente código:
int i2a_old(int n, char *s)
{
char d,*e=s;//init begin pointer
do{*e++=''0''+n%10;}while(n/=10);//extract digits
*e--=0;//set end of str_number
int digits=e-s;//calc number of digits
while(s<e)d=*s,*s++=*e,*e--=d;//reverse digits of the number
return digits;//return number of digits
}
Creo que la función printf (...) hace algo así.
Ahora voy a escribir esto:
int i2a_new(int n, char *s)
{
int digits=n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10;
char *e=&s[digits];//init end pointer
*e=0;//set end of str_number
do{*--e=''0''+n%10;}while(n/=10);//extract digits
return digits;//return number of digits
}
Ventajas: tabla de búsqueda indipendiente; C, C ++, Java, JavaScript, PHP compatible; obtener el número de dígitos, min comparisons: 3
; obtener el número de dígitos, max comparisons: 4
; código rápido; una comparación es muy simple y rápida: cmp reg, immediate_data
-> 1 CPU clock.
He visto muchas respuestas, pero todas olvidaron usar do {...} while()
loop, que en realidad es la forma canónica de resolver este problema y manejar 0
correctamente.
Mi solución se basa en this de Naveen .
int n = 0;
std::cin>>n;
std::deque<int> digits;
n = abs(n);
do {
digits.push_front( n % 10);
n /= 10;
} while (n>0);
La versión entera es trivial:
int fiGetDigit(const int n, const int k)
{//Get K-th Digit from a Number (zero-based index)
switch(k)
{
case 0:return n%10;
case 1:return n/10%10;
case 2:return n/100%10;
case 3:return n/1000%10;
case 4:return n/10000%10;
case 5:return n/100000%10;
case 6:return n/1000000%10;
case 7:return n/10000000%10;
case 8:return n/100000000%10;
case 9:return n/1000000000%10;
}
return 0;
}
Lo siguiente imprime los dígitos en orden ascendente (es decir, unidades, luego decenas, etc.):
do {
int digit = n % 10;
putchar(''0'' + digit);
n /= 10;
} while (n > 0);
No es tan genial como la respuesta de Martin York, sino que aborda un problema arbitrario:
Puede imprimir un entero positivo mayor que cero simplemente con recursión:
#include <stdio.h>
void print(int x)
{
if (x>0) {
print(x/10);
putchar(x%10 + ''0'');
}
}
Esto imprimirá el último dígito menos significativo.
Obtenga todos los dígitos individuales en algo como una matriz, dos variantes:
int i2array_BigEndian(int n, char a[11])
{//storing the most significant digit first
int digits=//obtain the number of digits with 3 or 4 comparisons
n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10;
a+=digits;//init end pointer
do{*--a=n%10;}while(n/=10);//extract digits
return digits;//return number of digits
}
int i2array_LittleEndian(int n, char a[11])
{//storing the least significant digit first
char *p=&a[0];//init running pointer
do{*p++=n%10;}while(n/=10);//extract digits
return p-a;//return number of digits
}
Primer dígito (menos significativo) = num% 10, segundo dígito = piso (num / 10)% 10, tercer dígito = piso (num / 100)% 10. etc
Use una secuencia de operaciones mod 10 y div 10 (cualquiera que sea la sintaxis en C ++) para asignar los dígitos uno a la vez a otras variables.
En pseudocódigo
lsd = number mod 10
number = number div 10
next lsd = number mod 10
number = number div 10
etc ...
¡doloroso! ... pero sin cadenas o matrices de caracteres.
Ya que todos están interviniendo sin saber la pregunta.
Aquí está mi intento de futilidad:
#include <iostream>
template<int D> int getDigit(int val) {return getDigit<D-1>(val/10);}
template<> int getDigit<1>(int val) {return val % 10;}
int main()
{
std::cout << getDigit<5>(1234567) << "/n";
}
recursión simple:
#include <iostream>
// 0-based index pos
int getDigit (const long number, int pos)
{
return (pos == 0) ? number % 10 : getDigit (number/10, --pos);
}
int main (void) {
std::cout << getDigit (1234567, 4) << "/n";
}