Вычисление среднего числа трех long long в си

Учитывая long long x, long long y и long long z, как можно вычислить ((x + y + z) / 3) с использованием полностью определенных операций в C, но исключая unsigned long long и более широкую арифметику?

Также я ограничен внесением изменений только внутри функции, которая должна найти среднее значение трех чисел.

Примечание: я уже пробовал искать решение, а также пробовал что-то вроде

#include <stdio.h>
long long average (long long a, long long b, long long c)
{
    long long n=0;
    n= a / 3 + b / 3 + c / 3 + (a % 3 + b % 3 + c % 3) / 3;
    return n;
}

Ответы (4 шт):

Автор решения: Zhihar

может так попробовать?

const long long x1 = a >> 32;
const long long x2 = a  & 0xFFFFFFFF;

const long long y1 = b >> 32;
const long long y2 = b & 0xFFFFFFFF;

const long long z1 = c >> 32;
const long long z2 = c & 0xFFFFFFFF;

res = (((x1 + y1 + z1) / 3) << 32) + (x2 + y2 + z2) / 3;
→ Ссылка
Автор решения: Zhihar
long long average (long long a, long long b, long long c)
{   
    int digits[100];
    memset(digits, 0, sizeof(int) * 100);
    
    // сложить 3 числа
    int pos = 0;
    
    int flag = 0;
    
    while (a != 0 || b != 0 || c != 0) {
        const int d1 = a % 10;
        a /= 10;
    
        const int d2 = b % 10;
        b /= 10;
    
        const int d3 = c % 10;
        c /= 10;
    
        const int res = d1 + d2 + d3 + flag;
        flag = res / 10;
    
        digits[pos++] = res % 10;
    }
    
    digits[pos++] = flag;
    
    
    // разделить на 3
    int digits_res[100];
    int pos_res = 0;
    
    int sum = 0;
    
    for (int index = pos - 1; index >= 0; index--) {
        const int digit = digits[index];
    
        sum = sum * 10 + digit;
    
        digits_res[pos_res++] = sum / 3;
    
        sum = sum % 3;
    }
    
    
    // собрать в число
    long long res = 0;
    
    for (int index = 0; index < pos_res; index++)
        res = res * 10 + digits_res[index];
    
    return res;
}
→ Ссылка
Автор решения: Джонни Кэтсвилл

Не воспроизводится.

Код:

#include <stdio.h>
#include <assert.h>

long long average (long long a, long long b, long long c)
{
    long long n=0;
    n= a / 3 + b / 3 + c / 3 + (a % 3 + b % 3 + c % 3) / 3;
    return n;
}

int main(void)
{
    long long a=9223372036854775800;
    long long b=4611686018427387897;
    long long c=3;

    printf("%lld\n", average(a, b, c));
    printf("%lld\n", 4611686018427387900);

    assert (average ( 9223372036854775800, 4611686018427387897, 3 ) == 4611686018427387900 );
}

https://ideone.com/Cm2vKo

4611686018427387900
4611686018427387900

→ Ссылка
Автор решения: wololo

Ваш код не учитывает работу с отрицательными числами.

Пусть квадратные скобки [...] обозначают операцию отбрасывания дробной части вещественного числа, a, b, c — целые вещественные числа, тогда:

Формула №1

Введём обозначения:

Формула №2

Тогда получим:

Формула №3

Заметим, что x, y — целые числа, а модуль значения y/3 принадлежит полуинтервалу [0, 1). В зависимости от знаков значений x и y итоговый результат будет следующим:

x == 0 || y == 0  =>  result == x,
x > 0 && y > 0    =>  result == x,
x > 0 && y < 0    =>  result == x-1,
x < 0 && y > 0    =>  result == x+1,
x < 0 && y < 0    =>  result == x.

Таким образом, функция нахождения среднего значения будет выглядеть как-то так:

long long average(long long a, long long b, long long c)
{
    long long rem_sum = a % 3 + b % 3 + c % 3;
    long long x = a / 3 + b / 3 + c / 3 + rem_sum / 3;
    long long y = rem_sum % 3;

    int coef1 = -(x > 0 && y < 0);
    int coef2 = +(x < 0 && y > 0);

    return x + coef1 + coef2;
 }

Ну, и несколько проверок:

 #include <stdio.h>

 long long average(long long a, long long b, long long c){...}

 int main(void)
 {
    long long min = -9223372036854775807 - 1;
    long long max = 9223372036854775807;

    printf("%d", average(min, min,   min)   ==  min         );
    printf("%d", average(max, max,   max)   ==  max         );
    printf("%d", average(min, min+1, min+2) ==  min+1       );
    printf("%d", average(max, max-1, max-2) ==  max-1       );
    printf("%d", average(max,  1,     2)    ==  max/3 + 1   );
    printf("%d", average(max, -1,    -2)    ==  max/3 - 1   );
    printf("%d", average(min,  1,     2)    == -(max/3 - 1) );
    printf("%d", average(min, -1,    -2)    == -(max/3 + 1) );
    printf("%d", average(0,    0,     0)    ==  0           );
    printf("%d", average(2,    2,     2)    ==  2           );
    printf("\n");
    
    printf("%d", average(9223372036854775800, 4611686018427387897, 3) == 4611686018427387900);
    printf("%d", average(9223372036854775800, -6, -2) == 3074457345618258597);
    printf("\n");
 
    long long counter = 0;
    long long first = -32;
    long long last =   32;
    for (long long a = first; a <= last; ++a)
        for (long long b = first; b <= last; ++b)
            for (long long c = first; c <= last; ++c)
            {
                long long res = (a + b + c) / 3;
                if (average(a, b, c) != res)
                    ++counter;
            }
    printf("Errors: %lld\n", counter);
}

Вывод:

1111111111
11
Errors: 0
→ Ссылка