[英]Median Maintenance Algorithm - Same implementation yields different results depending on Int32 or Int64
我在做硬件問題時發現了一些有趣的東西。
howework問題要求對中位數維護算法進行編碼。
正式聲明如下:
這個問題的目標是實現“中位數維護”算法(在第5周關於堆應用程序的講座中介紹)。 文本文件包含從1到10000的整數列表(未排序)。 您應該將此視為一連串的數字,一一到達。 令x i表示文件的第 i 個數字,第k 個中位數m k定義為數字x 1 ,…,x k的中值 。 (因此,如果k為奇數,則m k為x 1 ,…,x k中的 第 ((k + 1)/ 2) 個最小數;如果k為偶數,則m 1為第(k / 2) 個最小數x 1 ,…,x k中的數字 。)
為了獲得O(n)的運行時間,顯然應該使用堆來實現。 無論如何,我使用“蠻力”(截止日期太早,需要立即回答)( O(n 2 ))進行編碼,並執行以下步驟:
我通過幾個測試用例(具有已知答案)運行了該算法,並獲得了正確的結果,但是當我在更大的數據集上運行相同的算法時,卻得到了錯誤的答案。 我正在使用Int64 ro代表數據進行所有操作。 然后我嘗試切換到Int32,神奇地得到了正確的答案,這對我來說毫無意義。
代碼在下面,也可以在此處找到(數據位於存儲庫中)。 在3810索引之后,該算法開始給出錯誤的結果:
private static void Main(string[] args)
{
MedianMaintenance("Question2.txt");
}
private static void MedianMaintenance(string filename)
{
var txtData = File.ReadLines(filename).ToArray();
var inputData32 = new List<Int32>();
var medians32 = new List<Int32>();
var sums32 = new List<Int32>();
var inputData64 = new List<Int64>();
var medians64 = new List<Int64>();
var sums64 = new List<Int64>();
var sum = 0;
var sum64 = 0f;
var i = 0;
foreach (var s in txtData)
{
//Add to sorted list
var intToAdd = Convert.ToInt32(s);
inputData32.Add(intToAdd);
inputData64.Add(Convert.ToInt64(s));
//Compute sum
var count = inputData32.Count;
inputData32.Sort();
inputData64.Sort();
var index = 0;
if (count%2 == 0)
{
//Even number of elements
index = count/2 - 1;
}
else
{
//Number is odd
index = ((count + 1)/2) - 1;
}
var val32 = Convert.ToInt32(inputData32[index]);
var val64 = Convert.ToInt64(inputData64[index]);
if (i > 3810)
{
var t = sum;
var t1 = sum + val32;
}
medians32.Add(val32);
medians64.Add(val64);
//Debug.WriteLine("Median is {0}", val);
sum += val32;
sums32.Add(Convert.ToInt32(sum));
sum64 += val64;
sums64.Add(Convert.ToInt64(sum64));
i++;
}
Console.WriteLine("Median Maintenance result is {0}", (sum).ToString("N"));
Console.WriteLine("Median Maintenance result is {0}", (medians32.Sum()).ToString("N"));
Console.WriteLine("Median Maintenance result is {0} - Int64", (sum64).ToString("N"));
Console.WriteLine("Median Maintenance result is {0} - Int64", (medians64.Sum()).ToString("N"));
}
更有意思的是,與使用LINQ的Sum()函數對列表中的所有項目求和相比,運行總和(在sum64變量中)產生的結果有所不同。
結果(第三個是錯誤的):
這些是計算機的詳細信息:
如果有人可以給我一些見解,我將不勝感激。
謝謝,
0f正在初始化32位浮點變量,這意味着0d或0.0會接收64位浮點。
至於linq,如果使用強類型列表,可能會得到更好的結果。
new List<int>()
new List<long>()
我注意到的第一件事是注釋程序執行的操作: var sum64 = 0f
將sum64初始化為浮點型。 由於Int64s集合的中位數本身就是Int64(指定的規則不使用偶數基數集合中兩個中點值之間的均值),因此您應該改為將變量明確聲明為long
。 實際上,我將繼續在此代碼示例中替換var
所有用法; var
的便利性在這里丟失了,導致了與類型相關的錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.