对数字的每一位进行平方并使用 C 将它们连接为数字(程序无法正确处理 0)

问题描述 投票:0回答:3

所以我被要求对数字的每个数字进行平方并将它们连接起来并使用 C 作为数字返回。但由于某种原因,我在处理 0 作为数字并在我的算法中实现它时遇到问题。例如:当 n = 3210987654 时,预期为 9410816449362516,但得到 941816449362516。

#include<math.h>
unsigned long long square_digits(unsigned n) {
    unsigned long long result = 0;
    int k = 0;
    int digits = (int)log10(n) + 1;
    for (int d = 0; d < digits; d++) {
        int digit = n % 10;
        int squared = digit * digit;
        n /= 10;
        if (d == 0) {
            result += squared * pow(10, k);
        }
        else {
            if (digit == 0) {
                k++;
            } 
            else if (digit < 4) {
                k++;
                result += squared * pow(10, k);
            } 
            else {
                k += 2;
                result += squared * pow(10, k);
            }
        }
    }
    return result;
}

所以我尝试使用变量 k ,它将作为 10 的幂,并根据连接平方数字所需的位数起作用。对于第一个数字,我保持简单,因为我没有更改 k 的值。对于其他人,我首先检查数字平方是否为 2 位数字。如果需要的话,那么每次我都必须增加功率两次,对于个位数平方一次。至于数字 0,我不能相应地相乘或连接,而是通过增加幂向左移动一步。根据我的假设,这应该可以完美地工作,但是这不能正常工作,因为它在处理数字中间的 0 时遇到问题。

例如:对于 n = 3210987654,预期为 9410816449362516,但得到 941816449362516

c numbers concatenation square
3个回答
1
投票

使用

pow
log10
使事情变得太复杂(甚至可能由于浮点计算而导致不正确)。进行整数计算时,全部使用整数。

保留一个

factor
变量,以便您知道在添加到结果之前将平方数与什么相乘。从
factor
1
开始,然后将每个平方数字乘以
10
100
,具体取决于平方数字的值。

类似:

unsigned long long square_digits(unsigned n) 
{
    unsigned long long result = 0;
    unsigned long long factor = 1;
    while (n) 
    {
        unsigned digit = n % 10;
        unsigned squared = digit * digit;
        result += factor * squared;
        factor = (squared >= 10) ? factor * 100 : factor * 10;
        n /= 10;
    }
    return result;
}

0
投票

要解决像这样的大数字的操作,通常最好通过将数字评估为字符串来完成,就像通常对信用卡号等大数字所做的那样。将数字转换为字符串后,可以根据问题场景的需要单独处理每个数字。这样,以下是数字平方函数的重构版本以及“主”函数中的测试工具。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned long long square_digits(long long n)
{
    char work[32];
    long long x = 1;
    long long result = 0;

    sprintf(work, "%lld", n);                               /* Store value in a string          */

    for (int i = (strlen(work) - 1); i >= 0; i--)           /* Evaluate each digit character    */
    {
        result += (work[i] - '0') * (work[i] - '0') * x;    /* Square the digit value and multiply by a succesive power of 10   */

        x *= 10;

        if (work[i] > '3')                                  /* Increase multiplier by 10 again for a two digit square           */
            x *= 10;
    }

    return result;
}

int main()
{
    long long i;

    printf("Enter a value: ");
    scanf("%lld", &i);

    printf("Result for %lld is %lld\n", i, square_digits(i));
    return 0;
}

以下是重点。

  • 要评估的整数值被转换为字符串值。
  • 从第一个数字开始,对每个字符进行平方,然后乘以一个工作变量,该变量的值连续增加“10”或“100”,具体取决于适应遇到“0”的平方数字的大小。
  • 计算完所有数字后,将返回结果

使用示例测试此重构代码,创建了以下终端输出。

craig@Vera:~/C_Programs/Console/SquareInt/bin/Release$ ./SquareInt 
Enter a value: 3210987654
Result for 3210987654 is 9410816449362516

继续评估这条可能的路线。


0
投票

你的代码非常复杂且不清楚。通常这样的代码包含错误。

例如,考虑

n
等于
104

对于循环的第一次迭代

k
等于
0
:

int k = 0;

所以第一次迭代后

result
将是
16

下一个数字是

0
。在这种情况下,
k
会递增:

if (digit == 0) {
    k++;
} 

并且变得等于

1

那么最后一位数字等于

1
你有

else if (digit < 4) {
    k++;
    result += squared * pow(10, k);
} 

也就是说,

k
等于
2
,因此
result
等于
116
。然而
result
应等于
1016

在我看来,我可以建议一个更清晰和简单的解决方案,而不使用处理双值的辅助标准函数

pow
log10
..

你在这里。

#include <stdio.h>

unsigned int max_divisor( unsigned int n )
{
    const unsigned int Base = 10;

    unsigned int divisor = 1;

    while (!( n / divisor < Base ))
    {
        divisor *= Base;
    }

    return divisor;
}

unsigned long long square_digits( unsigned n )
{
    const unsigned int Base = 10;

    unsigned long long result = 0;

    unsigned int divisor = max_divisor( n );

    do
    {
        unsigned long long digit = n / divisor;

        digit *= digit;

        result = ( digit < 10 ? Base : Base * Base ) * result + digit;

        n %= divisor;
    } while (divisor /= Base);

    return result;
}

int main( void )
{
    for (unsigned int n = 0; n <= 10; ++n)
    {
        printf( "%u -> %llu\n", n, square_digits( n ) );
    }

    unsigned int n = 3210987654;
    printf( "%u -> %llu\n", n, square_digits( n ) );
}

程序输出为

0 -> 0
1 -> 1
2 -> 4
3 -> 9
4 -> 16
5 -> 25
6 -> 36
7 -> 49
8 -> 64
9 -> 81
10 -> 10
3210987654 -> 9410816449362516
© www.soinside.com 2019 - 2024. All rights reserved.