テキストファイルの暗号化の処理で行き詰っています

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
elle
記事: 39
登録日時: 10年前

テキストファイルの暗号化の処理で行き詰っています

#1

投稿記事 by elle » 10年前

こんばんは。
今私は、テキストをシーザー方式で暗号化するプログラムを作っています。
ただし文字をずらすのではなく、文字コードをずらしています。
純粋に定数分だけずらすことはできたので、ずらす値を乱数で取得する、ちょっとした改良版のようなものを作っています。
同じシード値を与えて逆方向にずらせば平文が得られる形です。

プログラムとしては、標準入力でファイルパスを取得し、(encrypted)という名前を付加した新規ファイルに暗号化結果を書き込み、
もしパスに(encrypted)が含まれていれば復号処理にする流れにしました。

コード:

#include <iostream>
#include <fstream>
#include <string>
#include <typeinfo>
#include <algorithm>
#include <random>
#include <iomanip>

using namespace std;

const string ENCRYPTION_SUFFIX("(encrypted)");
const string DECRYPTION_SUFFIX("(decrypted)");

enum class Operation{
	Encryption,
	Decryption
};

int main()
{
	string fileInPath, fileOutPath;
	cout.setf(ios_base::hex, ios_base::basefield);
	cout.setf(ios_base::showbase);

	mt19937 mt19937(0xffff);
	uniform_int_distribution<> dist(1, 3);

	while (true){

		// パス取得(stdin)
		cout << "type the path of the file you want to encrypt (you can also Drag and Drop the file).\n"
				"type \"0\" to quit this program.\n";
		getline(cin, fileInPath);

		// 0が入力されれば終了
		if (fileInPath == "0")
			break;

		// ""をはずす
		const auto endIt = remove(fileInPath.begin(), fileInPath.end(), '\"');
		fileInPath.erase(endIt, fileInPath.end());

		// ファイル名に(encrypted)が含まれていれば、復号化処理にする
		const Operation operation = fileInPath.find(ENCRYPTION_SUFFIX, fileInPath.find_last_of("\\/")) != string::npos ? Operation::Decryption : Operation::Encryption;

		try{
			// 入力元oepn
			ifstream filein(fileInPath.c_str());
			filein.exceptions(ifstream::badbit);

			// 出力先open(サフィックス追加)
			fileOutPath = fileInPath;
			fileOutPath.insert(fileOutPath.rfind("."), operation == Operation::Encryption ? ENCRYPTION_SUFFIX : DECRYPTION_SUFFIX);

			ofstream fileout(fileOutPath.c_str());
			fileout.exceptions(ofstream::badbit);

			// 暗号化(シーザー)
			string buf;
			while (getline(filein, buf)){
//				cout << buf << "\n";

				if (operation == Operation::Encryption && ofstream::eofbit)
					buf += "\n";

				for (auto&& elem : buf){
//					cout << setw(10) << static_cast<int>(elem) << " to ";
					elem += operation == Operation::Encryption ? dist(mt19937) : dist(mt19937) * -1;
//					cout << setw(10) << static_cast<int>(elem) << "\n";
				}

				// 0x5cがある場合はエスケープされないように直後に追加する
				size_t pos = 0;
				while ((pos = buf.find('\\', pos)) != string::npos){
					buf.insert(pos++, "\\");
				}
				fileout << buf;
//				cout << buf << "\n";
			}
		}
		catch (exception& e){
			cerr << "[ " << typeid(e).name() << " ] exception was thrown because of [ " << e.what() << " ]\n" << endl;
			return -1;
		}

		clog << (operation == Operation::Encryption ? "Encryption" : "Decryption") << " is successfully completed.\n\n";
	}

	clog << "end program..." << endl;

	return 0;
}
このプログラムに対し、

コード:

\n
新しいキーワード\n
このようなテキストファイルをあてがうと、2行目を読み込んだ時に、(プログラムの)75行目のwhile文で無限ループに陥ってしまいます。(永久に'\\'が見つかってしまいposがどんどん増えていきます)

コメント部分はデバッグ表示用なのですが、はずして確かめてみると、
やはり暗号化した結果0x5cが出現したときに問題が起きているように思います(これが含まれないテキストは正常に暗号化・復号化できました)。

posの進め方が問題なのかと思い、posを前置にしたり、インクリメント自体なしも試したのですが、動作は変わらず、
+2や、前置インクリメントしてその後別に+1だと止まらなくはなったものの正しい結果が得られなくなりました。
(このようになります)

コード:

噌し€」ガ€[[ワ―ト	
(ちなみに75行目からのwhile文なしの場合はこうなりました)

コード:

燦┨ΕМ・ワ‐J
insertした後で位置を進めておけば、ちょうど挿入した直後の位置になるかと思ったのですが、意図したとおりになりません…。
どのようにするのが良いでしょうか?

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

Re: テキストファイルの暗号化の処理で行き詰っています

#2

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

elle さんが書きました:posの進め方が問題なのかと思い、posを前置にしたり、インクリメント自体なしも試したのですが、動作は変わらず、
+2や、前置インクリメントしてその後別に+1だと止まらなくはなったものの正しい結果が得られなくなりました。
このコードを提示できますか?
これではうまくいかない、ということですか?

コード:

#include <cstdio>
#include <string>
using std::string;

int main(void) {
	std::string buf="新しいキーワード\\n";
	size_t pos = 0;
	while ((pos = buf.find('\\', pos)) != string::npos){
		buf.insert(pos, "\\");
		pos+=2;
	}
	puts(buf.c_str());
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: テキストファイルの暗号化の処理で行き詰っています

#3

投稿記事 by h2so5 » 10年前

根本的な問題として、暗号化時に文字が改行コードに変換されてしまった場合はどうするのでしょうか?
復号するときにgetlineで正常に読み込めないと思うのですが。

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

Re: テキストファイルの暗号化の処理で行き詰っています

#4

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

そもそも「0x5cがある場合はエスケープされないように直後に追加する」という処理は必要なのですか?
蛇足ではないですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#5

投稿記事 by elle » 10年前

みけCATさん
あ…こんな簡単なことを見落としていたとは…
たしかにそのstringだと自分のコードでは無限ループになりますね。(そしてその状態が出現して無限ループになっていたのですね)
そうしますと、文字コードでずらすのは困難で、アルファベットをずらすようにするべきでしょうか…

h2so5さん
改行コードに変換された場合でも、そこでgetlineが区切られますので、
読み込んだ後に改行コードを末尾に追加することで(63~64行目)元の文を復元していますので、
この点に関しては問題はない…つもりです。

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#6

投稿記事 by elle » 10年前

みけCATさん
エスケープなしで、No.1の2番目ような結果になってしまったので、
このページなどを見て入れた方がいいのかと思ったのですが、
入れても入れなくても正しい結果にならないということは別の原因が有るのかもしれません…。

定数でずらす方でこの関連をもう少し試してみます。

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#7

投稿記事 by elle » 10年前

みけCATさん
すいません、早とちりしてました。
みけCATさんがNo.2で提示されたコードは正確に結果が出力されますね。
失礼しました。

何パターンか試してみましたが、日本語との絡みも含めて0x5c(\)もそのまま表示できるように思えましたので、
おっしゃる通りエスケープシーケンスの追加は蛇足でした。
別の箇所に原因が有るのでしょうか…。
► スポイラーを表示
このコードに対し、

コード:

表[]

]表[

][表

表][

このテキストを暗号化させると、定数(67行目を消して68行目を使用)の場合は正常に復号化され、乱数の場合は

コード:

顛\\
^房[
\Z望		房[Z
こうなってしまいます…。
うーん…、原因が見当もつきません…。

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

Re: テキストファイルの暗号化の処理で行き詰っています

#8

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

h2so5 さんが書きました:根本的な問題として、暗号化時に文字が改行コードに変換されてしまった場合はどうするのでしょうか?
復号するときにgetlineで正常に読み込めないと思うのですが。
ここで指摘されているとおり、'\'より改行コード(\x0d,\x0a)をエスケープするべきです。
もちろん、復号化するときは文字コードをずらす前にエスケープを元に戻さないといけません。
また、もちろんエスケープに'\'を使うなら、'\'もエスケープしないといけません。

【補足】
暗号化: 入力→ずらす→エスケープ→出力
復号化: 入力→エスケープ解除→逆にずらす→出力
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ジャガ

Re: テキストファイルの暗号化の処理で行き詰っています

#9

投稿記事 by ジャガ » 10年前

elle さんが書きました: 何パターンか試してみましたが、日本語との絡みも含めて0x5c(\)もそのまま表示できるように思えましたので、
試されたパターンに水平タブ(0x09)を含んだものはありますか?

コード:

顛\\
^房[
\Z望		房[Z
こうなってしまいます…。
うーん…、原因が見当もつきません…。
どのような手順で復号化しましたか?
起動>暗号化>終了(0入力)>起動>復号化
という手順ならとりあえず(h2so5さんのご指摘のケースを除き)復号化できそうな気がします。

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#10

投稿記事 by elle » 10年前

みけCATさん
ありがとうございます。返信が遅れてすいません。
ご意見を元にプログラムを改良しました。
(h2so5さん、見当違いな返信をしてしまいすいませんでした。)
► スポイラーを表示
このコードでの暗号化・復号化は以下のようになりました。
► スポイラーを表示
途中まではほぼ成功したのですが、途中からすっぽり抜けていました。
EOFが関係あるのかと思い、調べたところ0x1aがEOFとして取り扱われることがあるとの情報があったので、
0x1aもエスケープするようにしたところ、上記のテキストに対しては最後まで正しく復号されました。
しかし、これがもっと長いファイルになると、
例えば0123456789\nを1行としてこれが1000行あるファイルだと、途中から全く違う文字に復号されてしまいます。

下記のようなコードにしてdebug print部でブレークさせてみると、
► スポイラーを表示
0x5cが2回連続している場所でずれのようなものが発生しているようです。
何が原因なのでしょうか…。

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#11

投稿記事 by elle » 10年前

ジャガさん
ありがとうございます。
水平タブは無かったと思います。
改良したコードでは、No.7の内容は正常に暗号化・復号化できました。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: テキストファイルの暗号化の処理で行き詰っています

#12

投稿記事 by h2so5 » 10年前

直前のエスケープ文字だけ見ても意味がないですよ。
"\\\\\n" と "\\\\\\n" では\nの解釈が違いますが直前だけ見ても区別できませんよね。

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#13

投稿記事 by elle » 10年前

h2so5さん
あっ、そうでした…。ありがとうございます。

皆さんのアドバイスのおかげで完成しました!
長大なテキストなどでテストして完全一致したのでほぼ完成だと思います。ありがとうございます!
(暗号化はちょちょいっとずらすだけかと思っていたのですが、これだけの処理が必要なのですね…)

コード:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <algorithm>
#include <random>
#include <typeinfo>

using namespace std;

// constants
const string ENCRYPTION_SUFFIX("(encrypted)");
const string DECRYPTION_SUFFIX("(decrypted)");
const string NL_ESC("\\n");
const string CR_ESC("\\r");
const string EOF_ESC("\\e");
const string ESC_ESC("\\\\");

// global variables
static ifstream filein;
static ofstream fileout;
static string fileInPath, fileOutPath;
static mt19937 randmt(0xffff);
static uniform_int_distribution<> dist(1, 255);

// bufをposから遡って\が偶数個なら素の文字、奇数個ならエスケープした文字
bool IsEscaped(const string& buf, const size_t pos)
{
	// \*を見つけた時点ですでに後ろに一つ\があるが、while終了後--する手間を省くため0から始める
	int count = 0;

	while (buf[pos - ++count] == '\\');

	return count & 1;
}

void ReplaceAll(string& buf, const string& target, const string& result)
{
	size_t pos = 0;
	size_t size = result.size();
	while ((pos = buf.find(target, pos)) != string::npos){
		buf.replace(pos, target.size(), result);
		pos += size;
	}
}

void ReplaceEscaped(string& buf, const string& target, const string& result)
{
	size_t pos = 0;
	size_t size = result.size();
	while ((pos = buf.find(target, pos)) != string::npos){
		if (IsEscaped(buf, pos)){
			buf.replace(pos, target.size(), result);
		}
		pos += size;
	}
}

void Encryption() 
{
	// 入力元oepn
	filein.open(fileInPath.c_str());

	// 出力先open
	fileOutPath = fileInPath;
	fileOutPath.insert(fileOutPath.rfind("."), ENCRYPTION_SUFFIX);

	fileout.open(fileOutPath.c_str());

	// 暗号化
	string buf;
	while (getline(filein, buf)){
		
		buf += "\n";

		// 暗号化
		for (auto&& elem : buf){
			elem += dist(randmt);
		}

		// \とNLとCR、EOFはエスケープして書き込む
		ReplaceAll(buf, "\\", ESC_ESC);
		ReplaceAll(buf, "\n", NL_ESC);
		ReplaceAll(buf, "\r", CR_ESC);
		ReplaceAll(buf, "\x1a", EOF_ESC);

		fileout << buf;
	}
}

void Decryption() 
{
	// 入力元oepn
	filein.open(fileInPath.c_str());

	// 出力先open
	fileOutPath = fileInPath;
	fileOutPath.insert(fileOutPath.rfind("."), DECRYPTION_SUFFIX);

	fileout.open(fileOutPath.c_str());

	// 暗号化
	string buf;
	while (getline(filein, buf)){

		// NLとCR、EOFを戻す
		ReplaceEscaped(buf, NL_ESC, "\n");
		ReplaceEscaped(buf, CR_ESC, "\r");
		ReplaceEscaped(buf, EOF_ESC, "\x1a");

		// \\は\に
		ReplaceAll(buf, ESC_ESC, "\\");

		// 復号化
		for (auto&& elem : buf){
			elem -= dist(randmt);
		}

		fileout << buf;
	}
}

int main()
{
	cout.setf(ios_base::hex, ios_base::basefield);
	cout.setf(ios_base::showbase);
	filein.exceptions(ifstream::badbit);
	fileout.exceptions(ofstream::badbit);

	void(*Management[])() = {Encryption, Decryption};

	while (true){

		// パス取得(stdin)
		cout << "type the path of the file you want to encrypt (you can also Drag and Drop the file).\n"
				"type \"0\" to quit this program.\n";
		getline(cin, fileInPath);

		// 0が入力されれば終了
		if (fileInPath == "0")
			break;

		// ""をはずす
		const auto endIt = remove(fileInPath.begin(), fileInPath.end(), '\"');
		fileInPath.erase(endIt, fileInPath.end());

		// ファイル名に(encrypted)が含まれていれば、復号化処理にする
		const bool toBeDecrypted = fileInPath.find(ENCRYPTION_SUFFIX, fileInPath.find_last_of("\\/")) != string::npos;

		try{
			// 必要な方を呼び出し
			Management[toBeDecrypted]();
		}
		catch (exception& e){
			cerr << "[ " << typeid(e).name() << " ] exception was thrown because of [ " << e.what() << " ]\n" << endl;
			return -1;
		}

		clog << (toBeDecrypted ? "Decryption" : "Encryption") << " is successfully completed.\n\n";
	}

	clog << "end program..." << endl;

	return 0;
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: テキストファイルの暗号化の処理で行き詰っています

#14

投稿記事 by h2so5 » 10年前

このような文字コードレベルでの暗号化は、普通はデータをバイナリデータとして扱うことが多いのでここまで複雑にはなりません。
今回のプログラムは暗号化後のデータもテキストファイルとして扱うような仕様になっているため、これだけのエスケープが必要になります。
暗号化の問題ではなくて、字句解析の問題ですね。

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#15

投稿記事 by elle » 10年前

h2so5さん
そうだったのですか…。
私もバイナリ処理は試したのですが、なぜかその時はgetlineに固執していてどうしても最後にゴミ文字が出てしまうので諦めていました。
冷静に考えればbinaryでgetlineはまずかったですね。

バイナリで作りなおしてみました(更に、4Gを超えるテキストファイルにも対応?してみました)。
確かにこちらの方が作りやすいですね…。

コード:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <algorithm>
#include <random>
#include <memory>
#include <typeinfo>

using namespace std;

typedef unsigned long long int ullong;

// constants
const string ENCRYPTION_SUFFIX("(encrypted)");
const string DECRYPTION_SUFFIX("(decrypted)");
const size_t ALLOCATE_LIMIT = 1 << 20; // 約1MB

// global variables
static ifstream filein;
static ofstream fileout;
static string fileInPath, fileOutPath;
static mt19937 randmt(0xffff);
static uniform_int_distribution<> dist(1, 255);

void Encryption() 
{
	// 入力元oepn
	filein.open(fileInPath.c_str(), ios::in | ios::binary);

	// 出力先open
	fileOutPath = fileInPath;
	fileOutPath.insert(fileOutPath.rfind("."), ENCRYPTION_SUFFIX);

	fileout.open(fileOutPath.c_str(), ios::out | ios::binary);

	// fileSize取得
	filein.seekg(0, filein.end);
	const ullong fileSize = filein.tellg();
	filein.seekg(0, filein.beg);

	// alloc
	const size_t allocateSize = fileSize < ALLOCATE_LIMIT ? static_cast<size_t>(fileSize) : ALLOCATE_LIMIT;
	shared_ptr<char> buf(new char[allocateSize]);

	// ブロックずつ暗号化して書き込む
	while (!filein.eof()){
		filein.read(buf.get(), allocateSize);
		const size_t length = static_cast<size_t>(filein.gcount());

		for (size_t i = 0; i < length; ++i){
			buf.get()[i] += dist(randmt);
		}

		fileout.write(buf.get(), length);
	}
}

void Decryption() 
{
	// 入力元oepn
	filein.open(fileInPath.c_str(), ios::in | ios::binary);

	// 出力先open
	fileOutPath = fileInPath;
	fileOutPath.insert(fileOutPath.rfind("."), DECRYPTION_SUFFIX);

	fileout.open(fileOutPath.c_str(), ios::out | ios::binary);

	// fileSize取得
	filein.seekg(0, filein.end);
	const ullong fileSize = filein.tellg();
	filein.seekg(0, filein.beg);

	// alloc
	const size_t allocateSize = fileSize < ALLOCATE_LIMIT ? static_cast<size_t>(fileSize) : ALLOCATE_LIMIT;
	shared_ptr<char> buf(new char[allocateSize]);

	// ブロックずつ復号化して書き込む
	while (!filein.eof()){
		filein.read(buf.get(), allocateSize);
		const size_t length = static_cast<size_t>(filein.gcount());

		for (size_t i = 0; i < length; ++i){
			buf.get()[i] -= dist(randmt);
		}

		fileout.write(buf.get(), length);
	}
}

int main()
{
	cout.setf(ios_base::hex, ios_base::basefield);
	cout.setf(ios_base::showbase);
	filein.exceptions(ifstream::badbit);
	fileout.exceptions(ofstream::badbit);

	void(*Management[])() = {Encryption, Decryption};

	while (true){

		// パス取得(stdin)
		cout << "type the path of the file you want to encrypt (you can also Drag and Drop the file).\n"
				"type \"0\" to quit this program.\n";
		getline(cin, fileInPath);

		// 0が入力されれば終了
		if (fileInPath == "0")
			break;

		// ""をはずす
		const auto endIt = remove(fileInPath.begin(), fileInPath.end(), '\"');
		fileInPath.erase(endIt, fileInPath.end());

		// ファイル名に(encrypted)が含まれていれば、復号化処理にする
		const bool toBeDecrypted = fileInPath.find(ENCRYPTION_SUFFIX, fileInPath.find_last_of("\\/")) != string::npos;

		try{
			// 必要な方を呼び出し
			Management[toBeDecrypted]();
		}
		catch (exception& e){
			cerr << "[ " << typeid(e).name() << " ] exception was thrown because of [ " << e.what() << " ]\n" << endl;
			return -1;
		}

		clog << (toBeDecrypted ? "Decryption" : "Encryption") << " is successfully completed.\n\n";
	}

	clog << "end program..." << endl;

	return 0;
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: テキストファイルの暗号化の処理で行き詰っています

#16

投稿記事 by h2so5 » 10年前

shared_ptrに配列を入れるときは、deleterを明示的に指定しないといけません。
何も指定しないと解放時にdelete[]ではなくdeleteを利用してしまいますから。

コード:

shared_ptr<char> buf(new char[allocateSize], default_delete<char[]>());

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#17

投稿記事 by elle » 10年前

h2so5さん
あ、自動で判別されると思っていました…。
ということは上のプログラムはまるまる1MBメモリ解放し忘れていたことに…
危ないところでした、ありがとうございます。

修正版:
► スポイラーを表示

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#18

投稿記事 by elle » 10年前

時間計測したら結構遅かったので高速化(というより遅すぎたのを改善)してみました。
上のコードでは3万行くらいのテキストの暗号化・復号化に2139ms程かかっていましたが、
1バイトずつ暗号化してたのを4バイトずつにすることにより540msほどになり、
mt19937をuniform_int_distriburionを取り除いて単に呼び出したら131msほどになりました。
更に、mt19937_64を使用することで88msほどになりました。

EncryptionもDecryptionもほぼ同じ処理なので、統合して内部で条件分岐したところ、
パフォーマンスの低下するかと思いきや、なぜかこちらの方が早いケースもあり、誤差の範囲に思えます。
(どちらも72ms~98msほど)
数万回通ってるはずなのに…最適化されているのでしょうか。

ご参考までに。
► スポイラーを表示

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: テキストファイルの暗号化の処理で行き詰っています

#19

投稿記事 by h2so5 » 10年前

elle さんが書きました: EncryptionもDecryptionもほぼ同じ処理なので、統合して内部で条件分岐したところ、
パフォーマンスの低下するかと思いきや、なぜかこちらの方が早いケースもあり、誤差の範囲に思えます。
(どちらも72ms~98msほど)
数万回通ってるはずなのに…最適化されているのでしょうか。
分岐するといっても符号が違うだけでその後の処理に影響がないですよね。
しかも関数の実行中は必ず同じ方に分岐するので、分岐予測の失敗もないですし。
パフォーマンスに差がないのは不思議なことではないと思います。

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#20

投稿記事 by elle » 10年前

h2so5さん
なるほど…確かにそうですね…。
逆アセンブルを確認してみると、純粋にje...jmpが1セット増えているだけでした。
jeが数万回増えるくらいでは動作に大きな影響はないということでしょうか。
if文は少ない方がいいと聞いたことがあったのですが、if文の負荷にもいろいろあるのですね。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: テキストファイルの暗号化の処理で行き詰っています

#21

投稿記事 by h2so5 » 10年前

elle さんが書きました: jeが数万回増えるくらいでは動作に大きな影響はないということでしょうか。
if文は少ない方がいいと聞いたことがあったのですが、if文の負荷にもいろいろあるのですね。
私もそんなに詳しくはないですが、if文を少なく、というのはパイプラインハザードやキャッシュミスの発生率を下げるのが目的なんじゃないかと思います。
今回の場合は、条件分岐を入れてもそのような問題が起きるコードではないはずです。

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#22

投稿記事 by elle » 10年前

h2so5さん
そういうことでしたか…if文=重いもの、と思い込んでいました。
ということはやはりif文も工夫して使えばパフォーマンスに必ずしも悪影響ではないということですね。

関数の統合に関して今日改めて試行したところ、
暗号化の方が速度に差がない点は同じでしたが、復号化の方は * -1してる分10ms程遅くなっていました(なぜ気づかなかったのか…)。
ビット演算に変えたらほぼ同じ速度になりました。

やはりかかる時間の大部分は乱数の生成のようなので、XORShiftに変えたところさらに10msほど速くなりました(67ms)。
更に、リリースビルドにしたところ30ms(!)になりました。こんなに違うとは…。
このあたりが限界…でしょうかね。
► スポイラーを表示

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: テキストファイルの暗号化の処理で行き詰っています

#23

投稿記事 by h2so5 » 10年前

ちなみに、リリースビルドすると * -1 の部分も最適化されるのでビット演算にする意味はないです。

elle
記事: 39
登録日時: 10年前

Re: テキストファイルの暗号化の処理で行き詰っています

#24

投稿記事 by elle » 10年前

h2so5さん
あ…本当ですか…_| ̄|○
知りませんでした…。

閉鎖

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