1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C > Excel Trend()のC実装 / ExcelのTrend()の引数の順番に注意

Last updated at Posted at 2016-08-30
動作環境
stdint.hが使えない組込みC

http://qiita.com/7of9/items/c1e67a19efcfa7eed500
でC#実装したExcelのTrend()関数をCで実装した。

# include <stdio.h>
# include <stdbool.h>
# include <math.h>

typedef struct point {
	float x, y;	
} point_t;

float calcAverageValues(point_t *points, int size, bool isX)
{
	double sum = 0.0;
	for(int idx=0; idx<size; idx++) {
		if (isX) {
			sum += points[idx].x;
		} else {
			sum += points[idx].y;
		}
	}
	return sum / (float)size;
}

float calcSumDiffXDiffY(point_t *points, int size, float xBar, float yBar)
{
	double sum = 0.0;
	
	for(int idx=0; idx<size; idx++) {
		sum += (points[idx].x - xBar) * (points[idx].y - yBar);
	}
	return sum;
}
float calcSumDiffXSquared(point_t *points, int size, float xBar)
{
	double sum = 0.0;
	double xdiff;
	
	for(int idx=0; idx<size; idx++) {
		xdiff = (points[idx].x - xBar);
		sum += xdiff * xdiff;
	}
	return sum;
}

float SlopeOfPoints(point_t *points, int size)
{
	float xBar = calcAverageValues(points, size, /*isX=*/true);
	float yBar = calcAverageValues(points, size, /*isX=*/false);

	float dividend = calcSumDiffXDiffY(points, size, xBar, yBar);
	float divisor = calcSumDiffXSquared(points, size, xBar);
	
	return dividend / divisor;
}

float YInterceptOfPoints(point_t *points, int size, float slope)
{
	float xBar = calcAverageValues(points, size, /*isX=*/true);
	float yBar = calcAverageValues(points, size, /*isX=*/false);

	return yBar - (slope * xBar);	
}

float LeastSquaresValueAtX(point_t *points, int size, float x) {
	float slope = SlopeOfPoints(points, size);
	float yIntercept = YInterceptOfPoints(points, size, slope);

	return (slope * x) + yIntercept;
}

int main(void) {
	point_t P[] = {
		{ 600, 6 }, // X,Y
		{ 800, 7 },
		{ 1000, 10 },
		{ 1200, 12 },
		{ 1400, 14 },
	};
	int size = sizeof(P) / sizeof(P[0]);
	
	float res = LeastSquaresValueAtX(P, size, 650.0);
	printf("%.3f\n", res);
	return 0;
}
結果
Success	time: 0 memory: 2168 signal:0
6.125

同じ結果が出た。

各所のnamingが良くないが、とりあえずこれで。

エラー処理も入れた方がいいが、とりあえず。

ExcelのTrend()の引数の順番に注意

(追記 2016/09/06)

Excelの結果とC実装を比べていて、引数の順番に関してはまった。

Officeのサイトにおいて

書式
TREND(既知の y, [既知の x], [新しい x], [定数])
とある。

1つ目の引数(既知のy)と2つ目の引数(既知のx)を勘違いして反対に指定して、実際のデータを用いてEXCEL結果とC実装結果を比較する時にはまった。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?