質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

1回答

1236閲覧

多倍長整数演算で配列→数値→配列の計算

homepage1031

総合スコア15

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2021/10/18 13:43

編集2021/10/19 07:24

多倍長整数の演算で悩んでいます。
longまでしかない32bitマイコンでC言語で多倍長整数の演算を行いたいと思っています。

long longが使える元々実装されている以下のソースを、long longが実装されていない処理系に移植する必要があります。

C

1#define HUNDREDKETA 9 2const QWORD hundredk[HUNDREDKETA] = { 1L, // 0: 1の位 3 100L, // 1: 100の位 4 10000L, // 2: 5 1000000L, // 3: 6 100000000L, // 4: 7 10000000000L, // 5: 8 1000000000000L, // 6: 9 100000000000000L, // 7: 10 10000000000000000L };  // 8: 11 12static void HundredStrToDWord( BYTE *outd, int outlen, BYTE *ind, int length ) 13{ 14 int i, k; 15 QWORD wdt = 0; 16 17 // ind[4]:100000000Lの位,ind[5]:1000000Lの位,ind[6]:10000の位,ind[7]:100の位,ind[8]:1の位 18 for( i = 0,k=length-1; i < length; i++,k-- ) 19 wdt += (DWORD)ind[i] * hundredk[k]; 20 21 for( i = outlen-1; i >= 0; i-- ) 22 { 23 outd[i] = wdt & 0x0ff; 24 wdt >>= 8; 25 } 26}

実際の入出力例では
入力で01h,02h,11h(17),12h(18)が来た場合、
10進数で1021718(F9716h)とし、このデータをバイト毎に区切って
変換後の配列は0Fh,97h,16hになるような変換です。

■上記から理解した仕様
上記のソースと入出力例、及び、呼び出し元から以下の仕様になっていると思います。

引数として以下を受け取ります。
・*outd・・・出力先のバッファのポインタ
・outlen・・・上記バイト配列のデータ長 (1 ~ 64)
・ind・・・10進数の2桁毎の数値が入っているバイト配列
・length ・・・入力データ長 (9固定)

入力のバイト配列を
(何故そんな変換をするのかは分からないのですが)
これを10進数の整数値が2桁毎に配列に入っているとみなし、
10進数に変換後、再度、バイト配列に戻す関数を作りたいです。
ただし、変換後、出力先データ長より大きくなる場合は下の桁は切り捨てます。
01h,02h,11h(17),12h(18) → 1021718(F9716h) → 0Fh,97h,16h

入力が01h,02h,03h,04h,05h,06h,07h,08h,09h,10hとなった場合、
かつ、出力先バッファのデータ長が10、入力データ長 が9だった場合、
9バイト以降は切り捨てるので、10203040506070809(243F9C7CFE4719h)を二桁毎に区切って
24h,3Fh,9Ch,7Ch,FEh,47h,19hを出力先の配列の後ろに入れます。
なので、00h,00h,00h,24h,3Fh,9Ch,7Ch,FEh,47h,19hになります。

バイト配列は右詰になるため、9バイトに満たない場合は先頭の配列には00が入ります。

簡単に実装できるかと思ったのですが、実装しようと思ったらループが多く、
カラツバ法を調べてみたのですが、この繰り返しに対してどう実装して良いか分かりません。
何か良いアルゴリズムはありますでしょうか?

以上です。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2021/10/18 14:59 編集

> 入力として9バイトまでのバイト配列があり、 > これを10進数の9桁の整数値に変換する関数を作りたいです。 ...おかしくね? > 入力で01h,02h,11h,22hが来た場合、 > 10進数で1021122と見なし、 ってことは1byteが10進2桁に相当するんよね? だったら 9byteの配列は 10進18桁、「10進数の9桁の整数値に変換」なわけがない。 加えて「10進数の9桁の整数値に変換」でありながら > 変換後の配列は00h,0Fh,97h,16hになるような変換 とはどーゆーこと? それ16進じゃん。 > 10進数で1021122と見なし、 > 変換後の配列は00h,0Fh,97h,16hになるような変換です。 どんな変換ですか? 1021122 は 0x0F94C2 ですけど?
otn

2021/10/18 18:16

「入力として~」の3行と、「入力で~」の3行で言ってることが違うので、どちらかが間違いなのでしょうが、首尾一貫するように訂正しましょう。
homepage1031

2021/10/19 04:33

すいませんでした。 間違いや推測もありましたので書き直しました。
guest

回答1

0

ベストアンサー

入力で01h,02h,11h(17),22h(18)が来た場合、

22h(18) ではなく、12h(18) ですよね。

実装しようと思ったらループが多く、

次のコードはループが多くてダメですか?

C

1#include <stdio.h> 2 3typedef unsigned char BYTE; 4 5void HundredStrToDWord(BYTE *outd, int outlen, BYTE *ind, int length) 6{ 7 for (int i = 0; i < outlen ; i++) outd[i] = 0; 8 for (int i = 0; i < length; i++) 9 for (int c = ind[i], j = outlen; --j >= 0; c >>= 8) 10 outd[j] = c += outd[j] * 100; 11} 12 13int main(void) 14{ 15 BYTE a[9] = { 0, 0, 0, 0, 0, 1, 2, 17, 18 }; 16 BYTE b[5]; 17 HundredStrToDWord(b, 5, a, 9); 18 for (int i = 0; i < 5; i++) printf(" %02Xh", b[i]); 19 putchar('\n'); 20}

投稿2021/10/19 07:24

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

homepage1031

2021/10/20 08:32

> 22h(18) ではなく、12h(18) ですよね。 すいません、その通りです。 > 次のコードはループが多くてダメですか? 最小限のループで実装してあり可読性も高く素晴らしいと思いました。 見るとそうだなと思うのですが思いつきませんでした。 私の作ったものは ・出力先バッファを初期化するループ ・一時バッファを初期化するループ ・length分のループ内で、桁数分全て100倍するループと桁数分全て桁あふれを計算するループ ・一時バッファを出力先にコピーするループ に分かれて、ループが多すぎて見れたものではありませんでした。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問