C言語 数字を10分割するプログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
超初心者

C言語 数字を10分割するプログラム

#1

投稿記事 by 超初心者 » 2年前

過去に授業でC言語をほんのちょっと習いましたが,時がたちほとんど忘れてしまい,完全なる初心者です.

数字を10分割するプログラムを早急に作成したいのですが,やりかたがさっぱりわからず手詰まり状態です.
語彙力がなく言葉で説明が難しいので,例を挙げると,

エクセルから
"1, 2, 4, 8...."
などと入力したデータを,
"1, 1.1, 1.2, 1.3 , 1.4, .... , 1.9, 2.0, 2.2, 2.4, 2.6, ... , 3.6, 3.8, 4.0, 4.4, 4.8, 5.2, ... , 7.6, 8.0..."
という風に,1個目と2個目の数字の間を10等分割,2個目と3個目の数字の間を10等分割,,,としたデータに変換して取り出したいのです.

つまり,100個のデータだとしたら,それぞれの間で等分割して1000個のデータに変換したいです.
改めて説明下手ですみません.

このコードの作成が実際簡単なのか難しいのかも検討がつかないので申し訳ありませんが,ご教示いただきたいです.

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: C言語 数字を10分割するプログラム

#2

投稿記事 by みけCAT » 2年前

超初心者 さんが書きました:
2年前
つまり,100個のデータだとしたら,それぞれの間で等分割して1000個のデータに変換したいです.
これは無理そうですね。
それぞれの区間を10分割すると、100個のデータからは1001個のデータが生成されます。
したがって、「等分割」「100個のデータを1000個のデータに変換」という条件を同時に満たすのは無理と考えられます。
ただし、データの最後が例示されていないため、最後のデータを省くことで1000個にする、という選択肢はあります。

1001個でよければ、データの分割は以下のようにできます。

コード:

#include <stdio.h>

int main(void) {
	double dataArray[] = {1, 2, 4, 8};
	int dataNum = sizeof(dataArray) / sizeof(*dataArray);
	int divideNum = 10;
	int i, j;
	printf("%g\n", dataArray[0]);
	for (i = 1; i < dataNum; i++) {
		for (j = 1; j <= divideNum; j++) {
			double data = dataArray[i - 1] + (dataArray[i] - dataArray[i - 1]) * j / divideNum;
			printf("%g\n", data);
		}
	}
	return 0;
}
あとは、「エクセルから取得したデータ」を読み込むところが一番難しいかもしれません。
csvファイルであれば、テキストなので
(エラー処理を無視し、対応フォーマットを限定すれば)scanfでも読み込めるかもしれません。
xlsファイルやxlsxファイルであれば、標準でないライブラリを使わないと難しいかもしれません。
エクセルのアプリケーションから直接データを読み取るのは…エクセルを操作するライブラリがあったかなあ?

というわけで、まずやるべきことは作るプログラムの仕様を決めることだと考えられます。

・100個のデータから1001個のデータを作るようにする?それとも最後のデータを省くなどして1000個にする?
・入力や出力のフォーマットは?
・入力元や出力先はどうやって指定する?
 (標準入出力のみに対応する、コマンドライン引数でファイルを指定できるようにする、GUIのフォームを作るなど)
・不正な入力への対応は?
・対応する値の範囲と精度は?
 ・浮動小数点数?
  ・標準のdoubleなどで対応できる程度?それとも多倍長?
 ・有理数?
  ・分数、特に無限小数になる分数を小数にせず、分数として処理する?
 ・複素数?
 ・文字列やその他?
  ・「間」をどう定義する?

など。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: C言語 数字を10分割するプログラム

#3

投稿記事 by みけCAT » 2年前

まず訂正をします。
100個のデータから生成されるデータは、1001個ではなく991個でした。
(最初のデータはそのまま使い、残り99個のデータ1個につき10個のデータが生成されると考えられるので)
すると、1000個のデータを得るには残りの9個をどうやって生成するのかを考える必要があります。

そして、991個のデータを生成する部分を一般化してみました。
後は、1000個ではなく991個でよいのであれば、
入出力と間の値を計算する部分の仕様を決め、実装すれば、プログラムができるでしょう。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

/*
配列のデータを分割し、分割した配列を返す。
numResultElements : 分割結果の要素数を格納する場所のポインタ
array             : 分割する配列(の先頭要素へのポインタ)
numElements       : 配列の要素数
sizeOfElement     : 配列の1要素の大きさ
numOfDivide       : 何分割するか
interpolate       : 分割した間の値を計算する関数
	out         : 計算結果の値を格納する場所のポインタ
	from        : 分割する範囲の最初の値のポインタ
	to          : 分割する範囲の最後の値のポインタ
	place       : 何番目の値を求めるか (fromが0番目、toがnumOfDivide番目)
	numOfDivide : 何分割するか
*/
void* divideData(size_t* numResultElements,
const void* array, size_t numElements, size_t sizeOfElement, size_t numOfDivide,
void (*interpolate)(void* out, const void* from, const void* to, size_t place, size_t numOfDivide)) {
	if (numResultElements != NULL) *numResultElements = 0;
	if (numElements == 0 || array == NULL || sizeOfElement == 0 || numOfDivide == 0) {
		return NULL;
	} else if (numElements == 1) {
		void* res = malloc(sizeOfElement);
		if (res == NULL) return NULL;
		memcpy(res, array, sizeOfElement);
		if (numResultElements != NULL) *numResultElements = 1;
		return res;
	} else if (
	numElements - 1 > SIZE_MAX / numOfDivide ||
	(numElements - 1) * numOfDivide > SIZE_MAX - 1 ||
	(numElements - 1) * numOfDivide + 1 > SIZE_MAX / sizeOfElement) {
		return NULL;
	} else {
		const char* cArray = array;
		char* resultArray = malloc(sizeOfElement * ((numElements - 1) * numOfDivide + 1));
		size_t i, j;
		if (resultArray == NULL) return NULL;
		memcpy(resultArray, cArray, sizeOfElement);
		for (i = 1; i < numElements; i++) {
			for (j = 1; j < numOfDivide; j++) {
				interpolate(resultArray + sizeOfElement * ((i - 1) * numOfDivide + j),
					cArray + sizeOfElement * (i - 1),
					cArray + sizeOfElement * i,
					j, numOfDivide);
			}
			memcpy(resultArray + sizeOfElement * i * numOfDivide, cArray + sizeOfElement * i, sizeOfElement);
		}
		if (numResultElements != NULL) *numResultElements = (numElements - 1) * numOfDivide + 1;
		return resultArray;
	}
}

void interpolate_double(void* out, const void* from, const void* to, size_t place, size_t numOfDivide) {
	double fromValue = *(const double*)from;
	double toValue = *(const double*)to;
	*(double*)out = fromValue + (toValue - fromValue) * place / numOfDivide;
}

int main(void) {
	double dataArray[] = {1, 2, 4, 8};
	int dataNum = sizeof(dataArray) / sizeof(*dataArray);
	int divideNum = 10;
	size_t dividedNum = 0;
	double* divided;
	size_t i;
	divided = divideData(&dividedNum, dataArray, dataNum, sizeof(*dataArray), divideNum, interpolate_double);
	for (i = 0; i < dividedNum; i++) {
		printf("%g\n", divided[i]);
	}
	free(divided);
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

返信

“C言語何でも質問掲示板” へ戻る