假设您有一个int数组(使用任何固定大小的int语言)。你如何计算最接近它们平均值的int?
编辑:要清楚,结果不必存在于数组中。也就是说,对于输入数组[3,6,7],预期结果为5.此外,我想我们需要指定一个特定的舍入方向,所以如果你同样接近两个数字,请向下舍入。
编辑:这不是作业。我五年没有做过功课了。这是我第一次使用stackoverflow,所以请你好!
编辑:总结和划分的明显方法可能会溢出,所以我试图想出一种对于大型阵列和大型整数都是溢出安全的方法。我认为正确处理溢出(没有作弊和使用不同的类型)是这个问题中最困难的部分。
答案 0 :(得分:5)
这是一种快速,合理的溢出安全和可以预先知道元素数量的方法。
// The length of someListOfNumbers doesn't need to be known in advance.
int mean(SomeType someListOfNumbers) {
double mean = 0, count = 0;
foreach(element; someListOfNumbers) {
count++;
mean += (element - mean) / count;
}
if(count == 0) {
throw new UserIsAnIdiotException(
"Problem exists between keyboard and chair.");
}
return cast(int) floor(mean);
}
答案 1 :(得分:2)
通过将数字相加并除以它们的数量来计算总和,并使用舍入:
mean = (int)((sum + length/2) / length;
如果您担心溢出,可以执行以下操作:
int mean = 0, remainder = 0
foreach n in number
mean += n / length
remainder += n % length
if remainder > length
mean += 1
remainder -= length
if remainder > length/2
mean += 1
print "mean is: " mean
请注意,这不是很快。
答案 2 :(得分:2)
round(mean(thearray))
大多数语言都有允许您指定舍入方法的工具。
编辑:事实证明,这个问题实际上是关于避免溢出,而不是关于舍入。让我明确一点,我同意那些已经说过(在评论中)在实践中不需要担心的事情,因为它很少发生,并且当它发生时,你可以随时使用更大的数据类型。< / p>
我看到其他几个人给出的答案基本上是将数组中的每个数字除以数组的数量,然后将它们相加。这也是一个很好的方法。但只是为了踢,这里是另一种选择(在C-ish伪代码中):
int sum_offset = 0;
for (int i = 1; i < length(array); i++)
sum_offset += array[i] - array[i-1];
// round by your method of choice
int mean_offset = round((float)sum_offset / length(array));
int mean = mean_offset + array[0];
或者做同样事情的另一种方式:
int min = INT_MAX, max = INT_MIN;
for (int i = 0; i < length(array); i++) {
if (array[i] < min) min = array[i];
if (array[i] > max) max = array[i];
}
int sum_offset = max - min;
// round by your method of choice
int mean_offset = round((float)sum_offset / length(array));
int mean = mean_offset + min;
当然,您需要确保sum_offset
不会溢出,如果最大和最小数组元素之间的差异大于INT_MAX,则可能会发生这种情况。在这种情况下,用以下内容替换最后四行:
// round by your method of choice
int mean_offset = round((float)max / length(array) - (float)min / length(array));
int mean = mean_offset + min;
琐事:这种方法,或类似的方法,对于精神计算其元素紧密聚集在一起的数组的平均值也非常有效。
答案 3 :(得分:1)
保证不会溢出:
length ← length of list
average ← 0
for each result in the list do:
average ← average + ( result / length )
end for
如果你因为截断而使用整数(平均6个4分为0),这就会产生严重的准确性问题。
答案 4 :(得分:0)
欢迎。鱼,希望你的逗留愉快。
以下伪代码显示了如何在总和适合整数类型的情况下执行此操作,并将舍入舍入为最接近的整数。
在您的示例中,数字将总和加到16,除以3得到5 1/3,其舍入为5。
sum = 0
for i = 1 to array.size
sum = sum + array[i]
sum = sum / array.size
sum = round (sum)
答案 5 :(得分:0)
获得平均值的伪代码:
double mean = 0
int count = 0
foreach int number in numbers
count++
mean += number - mean / count
round(mean) // rounds up
floor(mean + 0.5) // rounds up
ceil(mean - 0.5) // rounds down
舍入通常涉及添加0.5,然后截断(下限),这就是为什么3.5轮到4轮。如果你想要3.5到向下舍入到3,请自己进行舍入代码,但反过来:减去0.5,然后找到上限。
编辑:更新了要求(无溢出)
答案 6 :(得分:0)
此伪代码找到平均值并涵盖溢出问题:
double avg = 0
int count = 0
for x in array:
count += 1
avg = avg * (count - 1) / count // readjust old average
avg += x / count // add in new number
之后,您可以应用舍入代码。如果没有简单的方法可以用你的语言进行舍入,那么这样的事情就可以了(当结束时为五舍五入):
int temp = avg - int(avg) // finds decimal portion
if temp <= 0.5
avg = int(avg) // round down
else
avg = int(avg) + 1 // round up
答案 7 :(得分:0)
ARM程序集。 =]未经测试。不会溢出。永远。 (我希望。)
可能会稍微优化一下。 (也许使用FP / LR?)= S也许THUMB在这里会更好用。
.arm
; r0 = pointer to array of integers
; r1 = number of integers in array
; returns mean in r0
mean:
stmfd sp!, {r4,r5}
mov r5, r1
mov r2, 0 ; sum_lo
mov r3, 0 ; sum_hi
cmp r1, 0 ; Check for empty array
bz .end
.loop:
ldr r4, [r0], #4
add r2, r2, r4
adc r3, r3, #0 ; Handle overflow
sub r1, r1, #1 ; Next
bnz .loop
.end:
div r0, r2, r3, r5 ; Your own 64-bit/32-bit divide: r0 = (r3r2) / r5
bx lr