Aquí está mi código:
#include <stdio.h> #include <math.h> int main() { int num, i = 0, new_num = 0, u; printf("Enter a number: "); scanf("%d", &num); while (num > 0) { u = num % 10; if (u % 2 == 0) u = u; if (u % 2 == 1) u = u - 1; new_num = new_num + u * pow(10, i); num = num / 10; i++; } printf("The new number is: %d", new_num); return 0; } Ahora, cuando estoy haciendo esto en gcc (VS Code), para un número de 2 dígitos, todo está bien. Pero para dígitos de más de tres recibo un error. Como Entrada= 23145 Salida= 22043 . Pero esperaba salida = 22044 .
Además, si ejecuto el mismo código en DevC/C++, no hay error.
¿Alguien puede ayudarme en esto?
Su programa produce el resultado esperado en mi sistema: 22044 para 23145 , pero esto podría depender de la implementación de la función pow .
La razón por la que obtiene un resultado diferente es probablemente un efecto secundario de un problema de precisión con la función pow() en su biblioteca C: si pow(x, y) se implementa como exp(y * log(x)) , el resultado de los valores integrales de x e y pueden ser muy cercanos pero inferiores al valor integral real, lo que hace que la conversión a int produzca el entero anterior. Algunos autores de bibliotecas de C hacen un caso especial de argumentos integrales para evitar este problema, pero se recomienda encarecidamente evitar las funciones de punto flotante para la aritmética de enteros para evitar problemas tan complicados.
Aconsejaría algunos cambios más en su código:
pruebe el valor de retorno de scanf() .
quita el if (u % 2 == 0) u = u; parte, no tiene ningún efecto.
en cualquier caso, debe haber una cláusula else para no usar el resultado del caso anterior al probar dígitos impares.
no use la función de coma flotante pow() : simplemente mantenga una variable multiplicadora y actualícela en el bucle.
el programa no maneja números negativos.
Aquí hay una versión modificada:
#include <stdio.h> int main() { int num, new_num = 0, pow10 = 1; printf("Enter a number: "); if (scanf("%d", &num) != 1) return 1; while (num != 0) { int digit = num % 10; /* decrement odd digits absolute value */ digit -= digit % 2; new_num = new_num + digit * pow10; pow10 = pow10 * 10; num = num / 10; } printf("The new number is: %d\n", new_num); return 0; } Tenga en cuenta que digit -= digit % 2; decrementará los dígitos impares positivos y en realidad incrementará los dígitos impares negativos, lo que efectivamente siempre decrementa el valor absoluto de los dígitos impares. De esta manera, tanto los valores positivos como los valores negativos se manejan correctamente.
Parece que el problema es usar la función pow que devuelve un valor doble.
Si está tratando con números enteros, es mejor evitar el uso de funciones que devuelven dobles debido a un posible truncamiento, entonces un doble se convierte en un número entero.
También preste atención a que el usuario puede ingresar un número negativo. Su programa permite hacer eso. En este caso su programa también producirá un resultado incorrecto.
yo escribiria el programa de la siguiente manera
#include <stdio.h> int main( void ) { while (1) { const int Base = 10; int num; printf( "Enter a number (0 - exit): " ); if (scanf( "%d", &num ) != 1 || num == 0) break; int new_num = 0; for (int tmp = num, multiplier = 1; tmp != 0; tmp /= Base) { int digit = tmp % Base; if (digit % 2 != 0) { digit += ( digit < 0 ? 1 : -1 ); } new_num = new_num + multiplier * digit; multiplier *= Base; } printf( "The original number is %d and the new number is: %d\n", num, new_num ); putchar( '\n' ); } }La salida del programa es
Enter a number (0 - exit): -123456789 The original number is -123456789 and the new number is: -22446688 Enter a number (0 - exit): 123456789 The original number is 123456789 and the new number is: 22446688 Enter a number (0 - exit): 0Si incluso los dígitos negativos suman -1, entonces debe sustituir esta declaración if
if (digit % 2 != 0) { digit += ( digit < 0 ? 1 : -1 ); }Para este
if (digit % 2 != 0) { digit = ( digit -1 ) % Base; }En este caso, la salida del programa podría verse como
Enter a number (0 - exit): -123456789 The original number is -123456789 and the new number is: -224466880 Enter a number (0 - exit): 123456789 The original number is 123456789 and the new number is: 22446688 Enter a number (0 - exit): 0 Es decir, en este caso, el nuevo valor para el valor negativo -123456789 será -224466880 .
En mi instancia de Visual Studio Code, para una entrada 23145, de hecho encuentro 22044 como salida.
Supongo que la divergencia viene con el elenco de pow(10,i) . La función Pow en C devuelve un doble que no es lo que realmente quieres aquí. Recomiendo encarecidamente no utilizar la función pow para la aritmética de enteros.
Una solución podría ser:
uint16_t i = 0u; uint16_t current_digit = 0u, decimal_digit = 1u; uint16_t new_number = 0u; uint16_t number = 23145u; while(number > 0u) { current_digit = number % 10; if (current_digit % 2) { current_digit = current_digit - 1; } new_number = new_number + current_digit * decimal_digit; decimal_digit *= 10u; number /= 10; i++; } printf("The new number is: %d", new_number);