[英]Write a program, which reads an Integer. Output another integer where the even digits are retained and odd digits are decremented by 1,
这是我的代码:
#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;
}
现在,当我在 gcc(VS 代码)中执行此操作时,对于 2 位数,一切正常。 但是对于超过三位的数字,我得到了一个错误。 比如输入= 23145
输出= 22043
。 但我期待 output= 22044
。
另外,如果我在 DevC/C++ 中运行相同的代码,也没有错误。
谁能帮我解决这个问题?
您的程序在我的系统上生成预期的 output: 22044
为23145
,但这可能取决于pow
function 的实现。
您得到不同 output 的原因可能是 C 库中pow()
function 的精度问题的副作用:如果pow(x, y)
实现为exp(y * log(x))
,则结果为x
和y
的整数值可能非常接近但不如实际的整数值,导致转换为int
产生前面的 integer。一些 C 库作者做了一个特殊情况的整数 arguments 来避免这个问题,但强烈推荐避免 integer 算术的浮点函数以防止此类棘手的问题。
我会建议您对代码进行更多更改:
测试scanf()
的返回值。
删除if (u % 2 == 0) u = u;
部分,它没有影响。
在任何情况下,都应该有一个else
子句,以便在测试奇数时不使用前一个案例的结果。
不要使用浮点数 function pow()
:只保留一个乘数变量并在循环中更新它。
该程序不处理负数。
这是修改后的版本:
#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;
}
注意digit -= digit % 2;
将递减正奇数位并实际递增负奇数位,这实际上总是递减奇数位的绝对值。 这样正值和负值都可以正确处理。
问题似乎是使用返回双精度值的 function pow
。
如果您正在处理整数,那么最好避免使用由于可能的截断而返回双精度的函数,然后双精度将转换为 integer。
还要注意用户可以输入负数。 您的程序允许这样做。 在这种情况下,您的程序也会产生不正确的结果。
我会按以下方式编写程序
#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' );
}
}
程序 output 是
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): 0
如果即使是负数也要加 -1 那么你应该用这个 if 语句代替
if (digit % 2 != 0)
{
digit += ( digit < 0 ? 1 : -1 );
}
对于这个
if (digit % 2 != 0)
{
digit = ( digit -1 ) % Base;
}
在这种情况下,程序 output 可能看起来像
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
也就是说,在这种情况下,负值-123456789
的新值将是-224466880
。
在我的 Visual Studio Code 实例中,对于输入 23145,我确实发现 22044 是 output。
我猜分歧来自pow(10,i)
的转换。 Pow function in C 返回一个 double,这不是你真正想要的。 我强烈建议不要将pow
function 用于 integer 算术。
一个解决方案可能是:
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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.