C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

2つの変数(2進数)から、計算を行う方法

[トピック内 11 記事 (1 - 11 表示)]  << 0 >>

■100371 / inTopicNo.1)  2つの変数(2進数)から、計算を行う方法
  
□投稿者/ パンの耳 (1回)-(2022/07/21(Thu) 23:32:57)

分類:[C/C++] 

はじめまして。
C言語で、以下の処理の実装方法について悩んでいます。

開発環境はVisualStudio 2019 になります。

とある関数を実行すると、1byte(char型)の変数が2つ取得できます。
これは、以下に記述するプログラムの、bit_topと、bit_lowとします。
取得部分は関係ないため省き、変数に初期値として入れています。

現在、このbit_topを上位のビット、bit_lowを下位のビットとして、1つの2進数の数値とし
(言い方間違えていたらすいません)
10進数、int型の数値として変数に入れています。
例えば、上位ビットが0xA0(1010 0000)、下位ビットが0x01(0000 0001)であった場合、2進数では
 1010 0000 0000 0001 となります。
これは、符号なしで表現する場合、40961という値になると思います。
この値は、以下のようにし、計算することができました。
 int val1 = (bit_top & 0xff) * 256 + (bit_low & 0xff);

これを、符号有り(2の補数? 先頭のビットが1であれば、負の値)で表現する場合、
-24575
になるかと思います。

これを、プログラムでどのように計算すれば良いか分からない為、助言をいただければと思います。
(そもそも符号なしの計算方法もよろしくないと思います)

以下プログラムです

#include <stdio.h>

int main(void)
{
char bit_top = 0xA0; // 1010 0000
char bit_low = 0x01; // 0000 0001

// 1010 0000 0000 0001 として、10進数に変換する(40961)
// 1010 0000(160) * 0000 00001 0000 0000(256) + 0000 0001(1) として計算
int val1 = (bit_top & 0xff) * 256 + (bit_low & 0xff);

// 同じく 1010 0000 0000 0001 を2の補数として計算したい
// int val2 =

printf("%d\n", val1);

return 0;
}

宜しくお願いします。
引用返信 編集キー/
■100372 / inTopicNo.2)  Re[1]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ KOZ (300回)-(2022/07/22(Fri) 01:04:27)
No100371 (パンの耳 さん) に返信
> 	int val1 = (bit_top & 0xff) * 256 + (bit_low & 0xff);
> 	// 同じく 1010 0000 0000 0001 を2の補数として計算したい
> 	// int val2 =

int val2 = (short)val1;

で求まりますが、これじゃ納得してもらえないんだろうなぁ。(^_^;)

int val3 = ((bit_top & 0x7f) << 8) + (bit_low & 0xff);
if (bit_top & 0x80) {
    val3 -= 0x8000;
}

これでどうでしょう?

引用返信 編集キー/
■100373 / inTopicNo.3)  Re[2]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ パンの耳 (2回)-(2022/07/22(Fri) 01:18:38)
No100372 (KOZ さん) に返信
> ■No100371 (パンの耳 さん) に返信
>> int val1 = (bit_top & 0xff) * 256 + (bit_low & 0xff);
>> // 同じく 1010 0000 0000 0001 を2の補数として計算したい
>> // int val2 =
>
> int val2 = (short)val1;
>
> で求まりますが、これじゃ納得してもらえないんだろうなぁ。(^_^;)

いえいえ!結果的に値が求めれれば問題ありません!
なるほど、キャスト方法は思いつきませんでした。


> int val3 = ((bit_top & 0x7f) << 8) + (bit_low & 0xff);
> if (bit_top & 0x80) {
> val3 -= 0x8000;
> }
>
> これでどうでしょう?

別解?も有難うございます。
こちらでも、正しく値求められることが確認できました!
(まだ原理は理解できておりませんが…)

ご回答ありがとうざいます、解決とさせて頂きます。


解決済み
引用返信 編集キー/
■100374 / inTopicNo.4)  Re[1]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ sima (1回)-(2022/07/22(Fri) 01:31:27)
No100371 (パンの耳 さん) に返信
> はじめまして。
> C言語で、以下の処理の実装方法について悩んでいます。
> 
> 開発環境はVisualStudio 2019 になります。
> 
> とある関数を実行すると、1byte(char型)の変数が2つ取得できます。
> これは、以下に記述するプログラムの、bit_topと、bit_lowとします。
> 取得部分は関係ないため省き、変数に初期値として入れています。
> 
> 現在、このbit_topを上位のビット、bit_lowを下位のビットとして、1つの2進数の数値とし
> (言い方間違えていたらすいません)
> 10進数、int型の数値として変数に入れています。
> 例えば、上位ビットが0xA0(1010 0000)、下位ビットが0x01(0000 0001)であった場合、2進数では

幾つか混乱か、誤記か判りませんが、誤りがあります。
上位ビット、下位ビットではなく、上位バイト、下位バイトでしょう。

1byte の変数が二つあって、型が char だとしていますが、 char は符号付なので、 0xA0 だと正の値ではなく
負の値だということに気付いていますか。

少しだけ余計なお世話な話をします。

ソースコードを読むだけでなく、デバッガーでシングルステップで変数の値が
どうなっているかにも注意して追いかけてみると見落としていた点に気付く事が
あるでしょう。

int が 16bit の整数の場合以下の様にすればいいでしょうね。

unsigned char hi = 0xa0;
unsigned char lo = 0x01;

unsigned int x = hi *256 + lo;  //正の値としたい場合
int y = lo * 256 + hi;          //負の値になってもいい場合


引用返信 編集キー/
■100375 / inTopicNo.5)  Re[3]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ KOZ (301回)-(2022/07/22(Fri) 08:02:55)
2022/07/22(Fri) 12:23:38 編集(投稿者)
No100373 (パンの耳 さん) に返信
> こちらでも、正しく値求められることが確認できました!
> (まだ原理は理解できておりませんが…)

あらためてみると、あまりカッコよくないです。(^_^;)
シフト演算するなら + より | でしょうし。

あるいは、補数(ビットを反転して + 1)を求めてゼロから差し引くとか

const int mask = 0xffff;
const int sign = 0x8000;
int val4 = ((bit_top & 0xff) << 8) | (bit_low & 0xff);
if (val4 & sign) {
    val4 = 0 - ((mask & ~val4) + 1); 
}

今回 16 ビットで計算していますが、この方法だと 6 ビットなども対応可能です。

解決済みのチェックが外れているのでつけておきます。

解決済み
引用返信 編集キー/
■100376 / inTopicNo.6)  Re[2]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ furu (172回)-(2022/07/22(Fri) 10:40:23)
No100374 (sima さん) に返信
> 1byte の変数が二つあって、型が char だとしていますが、 char は符号付なので、 0xA0 だと正の値ではなく
> 負の値だということに気付いていますか。
気付いているから & 0xff してるのでは?
引用返信 編集キー/
■100377 / inTopicNo.7)  Re[2]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ HattariB (27回)-(2022/07/22(Fri) 10:58:45)
No100374 (sima さん) に返信

> 1byte の変数が二つあって、型が char だとしていますが、 char は符号付なので、 0xA0 だと正の値ではなく
signed charはC言語の正当な型ですが、charがそれかどうかは、実装依存だった様な。
解決済み
引用返信 編集キー/
■100378 / inTopicNo.8)  Re[3]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ 魔界の仮面弁士 (3440回)-(2022/07/22(Fri) 11:06:32)
No100377 (HattariB さん) に返信
>>> C言語で、以下の処理の実装方法について悩んでいます。
>>> 開発環境はVisualStudio 2019 になります。
>> 1byte の変数が二つあって、型が char だとしていますが、 char は符号付なので、 0xA0 だと正の値ではなく
> signed charはC言語の正当な型ですが、charがそれかどうかは、実装依存だった様な。

char 型を signed char (-128〜127) とするか、unsigned char (0〜255) とするかは
/J オプションによって指定できますね。
https://docs.microsoft.com/ja-jp/cpp/build/reference/j-default-char-type-is-unsigned?view=msvc-170
https://docs.microsoft.com/ja-jp/cpp/cpp/data-type-ranges?view=msvc-170
解決済み
引用返信 編集キー/
■100379 / inTopicNo.9)  Re[3]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ furu (173回)-(2022/07/22(Fri) 12:43:49)
2022/07/22(Fri) 12:57:33 編集(投稿者)

No100377 (HattariB さん) に返信
> signed charはC言語の正当な型ですが、charがそれかどうかは、実装依存だった様な。

No100378 (魔界の仮面弁士 さん) に返信
> char 型を signed char (-128〜127) とするか、unsigned char (0〜255) とするかは
> /J オプションによって指定できますね。

https://docs.microsoft.com/ja-jp/cpp/cpp/char-wchar-t-char16-t-char32-t?view=msvc-170

C++なのに「もともとは C および C++ の文字型」と言っちゃってますね。
「signed char とも unsigned char とも異なる型です。」
signed charでもないです。

int に上位変換される時に
  /Jオプション無し  signed char 型からであるかのように変換
  /Jオプション有り  unsigned char型からであるかのように符号拡張なしで変換
引用返信 編集キー/
■100380 / inTopicNo.10)  Re[2]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ KOZ (302回)-(2022/07/22(Fri) 12:48:20)
No100374 (sima さん) に返信

気付いて修正しに来てくれないかなーとスルーしてたんですが(^_^;)

> 幾つか混乱か、誤記か判りませんが、誤りがあります。
> 上位ビット、下位ビットではなく、上位バイト、下位バイトでしょう。

上位8ビット、下位8ビットという言い方は普通にしますし、
説明もちゃんとしてらっしゃるので違和感はありませんでした。

あとは2箇所

> int が 16bit の整数の場合以下の様にすればいいでしょうね。

> int y = lo * 256 + hi; //負の値になってもいい場合

解決済み
引用返信 編集キー/
■100385 / inTopicNo.11)  Re[4]: 2つの変数(2進数)から、計算を行う方法
□投稿者/ HattariB (28回)-(2022/07/22(Fri) 19:10:05)
No100379 (furu さん) に返信
> 「signed char とも unsigned char とも異なる型です。」
> signed charでもないです。

「Microsoft コンパイラでは、char は 8 ビット型です。」
↑なるほど。オクテットである事を明確にしてるのは、良い事だと思います。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ