当前位置: 首页 > 知识库问答 >
问题:

3个长整数的平均值

窦伟
2023-03-14

我有3个非常大的有符号整数。

long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;

我想计算它们的截断平均值。预期平均值是long。MaxValue-1,即9223372036854775806

不可能计算为:

long avg = (x + y + z) / 3; // 3074457345618258600

注:我读了所有关于2个数字的平均值的问题,但我不知道该技术如何应用于3个数字的平均值。

使用BigInteger将非常容易,但假设我不能使用它。

BigInteger bx = new BigInteger(x);
BigInteger by = new BigInteger(y);
BigInteger bz = new BigInteger(z);
BigInteger bavg = (bx + by + bz) / 3; // 9223372036854775806

如果我转换为双精度,那么,当然,我会失去精度:

double dx = x;
double dy = y;
double dz = z;
double davg = (dx + dy + dz) / 3; // 9223372036854780000

如果我转换为decimal,它可以工作,但也让我们假设我不能使用它。

decimal mx = x;
decimal my = y;
decimal mz = z;
decimal mavg = (mx + my + mz) / 3; // 9223372036854775806

问题:有没有一种方法可以仅使用长类型来计算3个非常大整数的截断平均值?不要认为这个问题是C语言特有的,只是我更容易用C语言提供示例。

共有3个答案

朱天逸
2023-03-14

Patrick Hofman发布了一个很棒的解决方案。但如果需要,它仍然可以通过其他几种方式实现。使用这里的算法,我有另一个解决方案。如果仔细实施,它可能比硬件除数慢的系统中的多个除法更快。它可以通过使用除法常量技术进一步优化,黑客很高兴

public class int128_t {
    private int H;
    private long L;

    public int128_t(int h, long l)
    {
        H = h;
        L = l;
    }

    public int128_t add(int128_t a)
    {
        int128_t s;
        s.L = L + a.L;
        s.H = H + a.H + (s.L < a.L);
        return b;
    }

    private int128_t rshift2()  // right shift 2
    {
        int128_t r;
        r.H = H >> 2;
        r.L = (L >> 2) | ((H & 0x03) << 62);
        return r;
    }

    public int128_t divideby3()
    {
        int128_t sum = {0, 0}, num = new int128_t(H, L);
        while (num.H || num.L > 3)
        {
            int128_t n_sar2 = num.rshift2();
            sum = add(n_sar2, sum);
            num = add(n_sar2, new int128_t(0, num.L & 3));
        }

        if (num.H == 0 && num.L == 3)
        {
            // sum = add(sum, 1);
            sum.L++;
            if (sum.L == 0) sum.H++;
        }
        return sum; 
    }
};

int128_t t = new int128_t(0, x);
t = t.add(new int128_t(0, y));
t = t.add(new int128_t(0, z));
t = t.divideby3();
long average = t.L;

在64位平台上的C/C中,使用__int128要容易得多

int64_t average = ((__int128)x + y + z)/3;
叶允晨
2023-03-14

NB-帕特里克已经给出了一个很好的答案。在此基础上扩展,您可以对任意数量的整数执行通用版本,如下所示:

long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;

long[] arr = { x, y, z };
var avg = arr.Select(i => i / arr.Length).Sum() 
        + arr.Select(i => i % arr.Length).Sum() / arr.Length;
常子濯
2023-03-14

这段代码可以工作,但不是那么漂亮。

它首先将所有三个值相除(它将值分层,因此您将“丢失”余数),然后将余数相除:

long n = x / 3
         + y / 3
         + z / 3
         + ( x % 3
             + y % 3
             + z % 3
           ) / 3

注意,当有一个或多个负值时,上述样本并不总是正常工作。

正如与Ulugbek讨论的那样,由于下面的评论数量呈爆炸式增长,因此这是当前正值和负值的最佳解决方案。

感谢Ulugbek Umirov, James S, KevinZ, Marc van Leeuwen, gnasher729的回答和评论,这是当前的解决方案:

static long CalculateAverage(long x, long y, long z)
{
    return (x % 3 + y % 3 + z % 3 + 6) / 3 - 2
            + x / 3 + y / 3 + z / 3;
}

static long CalculateAverage(params long[] arr)
{
    int count = arr.Length;
    return (arr.Sum(n => n % count) + count * (count - 1)) / count - (count - 1)
           + arr.Sum(n => n / count);
}
 类似资料:
  • 问题内容: 我想要一种计算Java中任意两个整数x,y的方法。如果x + y> Integer.MAX_VALUE或<Integer.MIN_VALUE,那么幼稚的方法就会遇到问题。 番石榴 使用此技术: …但这朝着负无穷大方向舍入,这意味着例程与{-1,-2}之类的天真方式不同(给出-2而不是-1)。 是否有任何相应的例程截断为0? “仅使用”不是我想要的答案,因为我也想要一种适用于长时间输入的

  • 问题内容: 我有一个大小为N *M的矩阵,我想找到每一行的平均值。值是从1到5,并且没有任何值的条目设置为0。但是,当我想使用以下方法查找均值时,它给了我错误的均值,因为它还计算了具有值的条目0。 如何获得仅非零值的均值? 问题答案: 获取每一行的非零计数,并将其用于平均每一行的总和。因此,实现看起来像这样- 如果您使用的是较旧版本的NumPy,则可以使用count的float转换来替换,例如,

  • 问题内容: 我正在尝试学习SQL,所以请耐心等待。我正在使用PostgreSQL 9.3 我想根据日期窗口对一列进行平均。我能够编写窗口函数来完成一个集合,但是我希望能够随着不断增长做到这一点。我的意思是: 我假设有一个比对我要平均的每个范围运行查询更好的方法。任何建议表示赞赏。谢谢你。 编辑 我正在尝试创建均匀分布的垃圾箱,以用于汇总表的值。 我的间隔是: 这里是一个表的列 并且 是并列我想表分

  • 我需要写一个程序来计算用户输入的整数的奇偶平均数。用户键入“完成”以完成。输出将显示奇数的平均值和偶数的平均值。 我有一个while循环程序,可以计算数字的和,我正试图增加奇数和偶数和的额外要求。这是代码: 下面是我修改的代码,对奇数和偶数进行排序,然后对每组进行平均。 预期: 实际:

  • 希望这对你来说是有意义的,我很乐意更详细地解释这个问题。

  • Python是否有一个SciPy函数或NumPy函数或模块来计算给定特定窗口的一维数组的运行平均值?