c# 我怎样才能把两个25位数相加?

dbf7pr2w  于 2023-06-27  发布在  C#
关注(0)|答案(2)|浏览(288)

我正在尝试用C语言做25位数的加法。我得到的结果与预期的可能原因数据类型略有不同。

/* Online C Compiler and Editor */
#include <stdio.h>

int main()
{
    long double result;
    long double a;
    long double b;
    a = 51680708854858333333;
    b = 83621143489848333333,
    result = a + b ;
    printf("Hello, World!\n");
    printf("can be written %.0Lf\n", result);

    return 0;
}
ggazkfy8

ggazkfy81#

你可以用小学里教过的方法来做:

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

/*  Add two numbers represented by strings of digit characters.  The result is
    returned in dynamically allocated memory, which the caller is responsible
    for freeing.  The strings are not tested to ensure they contain only
    digits.

    The result may contain a leading zero.  This could be eliminated by testing
    after the addition, shifting all the characters left one space, and
    reallocating if desired.
*/
static char *add(const char *a, const char *b)
{
    //  Measure lengths of strings.
    size_t la = strlen(a);
    size_t lb = strlen(b);

    //  Plan space for result, allowing an extra character in case of carry.
    size_t lc = (la < lb ? lb : la) + 1;

    //  Allocate space for result digits plus a terminating null character.
    char *c = malloc(lc+1);
    if (!c)
    {
        fprintf(stderr, "Error, unable to allocate %zu bytes for sum.\n", lc+1);
        exit(EXIT_FAILURE);
    }
    c[lc] = '\0';

    /*  Add digits from right to left.  i counts positions from the right of
        the numerals.
    */
    int carry = 0;
    for (size_t i = 0; i < lc; ++i)
    {
        /*  Get digit from each addend.  While i is within a numeral, get its
            digit character and subtract '0' to convert it from a digit
            character ('0' to '9') to a plain number (0 to 9).  When i is
            outside the numeral, use zero.
        */
        int da = i < la ? a[la-1-i] - '0' : 0;
        int db = i < lb ? b[lb-1-i] - '0' : 0;
        
        /*  Add the digits, record the low digit of the sum in c, and calculate
            the carry to the next column.  The digit for c is converted from a
            plain number to a digit character.
        */
        int sum = da + db + carry;
        c[lc-1-i] = sum % 10 + '0';
        carry = sum/10;
    }

    return c;
}

int main(void)
{
    const char a[] = "51680708854858333333";
    const char b[] = "83621143489848333333";

    char *c = add(a, b);
    
    printf("sum = %s.\n", c);

    free(c);
}
pxy2qtax

pxy2qtax2#

你的代码中有一个小问题:用于初始化long double变量的文字5168070885485833333383621143489848333333实际上被解析为整数,并且它们都超过了最大整数类型long long int,即9223372036854775807
您必须添加尾随.以使它们成为浮点常量,并添加L以使long double成为常量。然后,您将获得更接近精确值的结果,受long double类型的精度限制:

#include <stdio.h>

int main()
{
    long double a = 51680708854858333333.L;
    long double b = 83621143489848333333.L;
    long double result = a + b;
    printf("%.0Lf + %.0Lf = %.0Lf\n", a, b, result);

    return 0;
}

我的macbook上的输出显示了long double类型的有限精度,使用M2芯片的默认编译器链:

51680708854858334208 + 83621143489848328192 = 135301852344706662400

为了更好的精度,你应该使用bignum包,但是对于25位数,如果你的编译器支持的话,你可以使用128位整数:

#include <stdio.h>

int main()
{
    long double a = 51680708854858333333.L;
    long double b = 83621143489848333333.L;
    long double result = a + b;
    printf("%.0Lf + %.0Lf = %.0Lf\n", a, b, result);

    __int128 e15 = 1000000000000000;
    __int128 aa = 51680 * e15 + 708854858333333;
    __int128 bb = 83621 * e15 + 143489848333333;
    __int128 cc = aa + bb;

    printf("%lld%015lld + %lld%015lld = %lld%015lld\n",
           (long long)(aa / e15), (long long)(aa % e15),
           (long long)(bb / e15), (long long)(bb % e15),
           (long long)(cc / e15), (long long)(cc % e15));

    return 0;
}

输出:

51680708854858334208 + 83621143489848328192 = 135301852344706662400
51680708854858333333 + 83621143489848333333 = 135301852344706666666

相关问题