65.9K
CodeProject 正在变化。 阅读更多。
Home

求平均数...简单的方法

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (3投票s)

2008年12月31日

CPOL

4分钟阅读

viewsIcon

23788

downloadIcon

135

如何求一组数字的平均值。

引言

在我上大学的时候,我们的第一个 (C) 编程作业是从文件中读取一组数字并求平均值。 我认为能够以这种方式获取数据非常酷。 让我们看看如何实现从输入文件中求一组数字的平均值。

Good

当时在一台 Unix 机器上,拥有似乎无限的磁盘空间,这意味着我们可以创建巨大的文件作为代码的输入。 我不记得这些机器的规格了,但即使是 MB 范围内的输入文件也可以在几秒钟内运行。 当你唯一的其他经验是使用 Commodore 便携式计算机时,即使是 10 分钟也会被视为一项突破!

在那次练习中,我了解到 fscanf() 的第一个参数是指向打开文件的句柄。 我还发现了这个名为 stdin 的东西,它是指向标准输入流的句柄,该句柄已经打开。 将 fscanf() 与标准输入流放在一起产生了一个看起来像这样的程序

int    nCount = 0,
       nNumber;
double dSum = 0.0;

while (fwscanf_s(stdin, _T("%d"), &nNumber) != EOF)
{
    dSum += nNumber;
    nCount++;
}

wprintf(_T("Average = %f\n"), dSum / nCount);

大多数熟悉 DOS 或 Unix 的人都知道如何重定向标准输入流。 从命令提示符来看,有两种方法是

type input_file | program.exe

program.exe < input_file

你也可以直接输入程序本身的名称,然后通过键盘输入数据,但这有什么乐趣呢? 这看起来很简单,但如果不正确使用,fwscanf_s() 可能会给你带来麻烦。 我想知道 C++ 是否有什么有用的东西可以提供...

更好

自从 MFC 诞生以来,我一直在使用它,但我没有早点学习 C++,这真是对不起我自己。 直到几年前,我才决定开始更多地学习 C++ 的基础知识以及 STL。 令人惊讶的是有多少小“工具”和算法可用。

ifstream fin;
vector<int> vNumbers;

fin.open(__wargv[1]);

copy(istream_iterator<int>(fin), istream_iterator<int>(), 
     back_inserter(vNumbers));

fin.close();

int nSum = accumulate(vNumbers.begin(), vNumbers.end(), 0);
    
wcout << (double) nSum / vNumbers.size();

要使用此版本,请在命令提示符下键入

program.exe input_file

与第一个选项相比,这是一个受欢迎的改进。 虽然 copy() 函数处理从输入文件读取并将所有内容存储在一个漂亮的小容器中,但 accumulate() 函数似乎在求和该容器中的所有内容方面做得很好。 但似乎仍然缺少一些东西...

最佳

在个人电脑和 Windows 操作系统时代,大多数人都使用过 Microsoft Excel,或者至少知道它是什么。 对于人群中的 Rip Van Winkles,Excel 是一个强大的工具,你可以用它来创建和格式化电子表格,以及分析和共享信息。 换句话说,它是一个非常强大的数字处理器。 拥有如此多的复杂性,肯定有一些东西可以毫不费力地求一组数字的平均值。

Excel 公开了一个我们可以利用的 COM 接口。 我们要做的第一件事是访问一个实际的工作表,我们可以在其中插入数字和公式。 要使用此 COM 接口,我们需要从 Excel 的类型库中导入信息。 这是通过 #import 指令完成的。 请注意,库 ID 是 Excel v12 (2007) 的 ID。

#import "libid:00020813-0000-0000-C000-000000000046" 
        version("1.6") 
        lcid("0") 
        auto_search 
        no_dual_interfaces 
        raw_dispinterfaces 
        auto_rename

此时,已经创建了一个 Excel 命名空间,我们可以使用它来限定每个变量的作用域。

Excel::_ApplicationPtr app;

HRESULT hr = app.CreateInstance(_T("Excel.Application"));
if (SUCCEEDED(hr))
{
    Excel::WorkbooksPtr books = app->GetWorkbooks();

    Excel::_WorkbookPtr book = books->Add();

    Excel::SheetsPtr sheets = book->GetWorksheets();

    // the argument to GetItem() is the 1-based sheet number
    Excel::_WorksheetPtr sheet = sheets->GetItem(COleVariant(1L));
}

现在我们可以访问一个实际的工作表,我们可以从输入文件 (__wargv[1]) 中读取数字并将它们插入到工作表的单元格中。 请注意,专门使用 A 列。

CStdioFile file;
if (file.Open(__wargv[1], CFile::modeRead))
{
    int     nRow = 1;
    CString str,
            strLine;

    while (file.ReadString(strLine))
    {
        // ranges are expected to be in the A1 format rather than the R1C1 format
        str.Format(_T("A%d"), nRow++);
        range = sheet->GetRange(COleVariant(str), vtOptional);

        range->PutValue2(COleVariant(strLine));
    }

    file.Close();
}

由于所有数字现在都插入到单元格中,我们需要插入一个函数来计算它们的平均值。 它的位置无关紧要(只要引用正确),但为了清楚起见,我们将其添加到最后一个数字的正下方。

str.Format(_T("A%d"), nRow);
range = sheet->GetRange(COleVariant(str), vtOptional);

str.Format(_T("=AVERAGE(A1:A%d)"), nRow - 1);
range->PutFormula(COleVariant(str));

最后一件事是获取 Excel 为我们计算的结果并将其打印到屏幕上。

COleVariant val = range->GetValue(COleVariant(10L));
wcout << _T("Average = ") << val.dblVal;

哇,终于找到了一些简单有用的东西! 我真希望我在大学的时候就能使用这种类型的功能。 想象一下我可以对这组数字执行的操作,例如求和、查找最小值和最大值、计算众数和中位数等等。 Excel 甚至可以让你对一系列数字进行排序。 ::wink:

尽情享用!

参考文献

© . All rights reserved.