7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pascal (Delphi) において 1 > 0 という式は、どのように評価されるのか?

Last updated at Posted at 2022-09-08

はじめに

Pascal において 1 > 0 という式は、どのように評価されるでしょうか?

  • -1
  • 0
  • 1
  • その他

解答&関連する話

答えは「その他」です。

Pascal の関係演算子 (=, <>, <=, <, >, >=, in) は論理型の結果を返すため、1 > 0 の場合には True となります。

EVTEST.pas
program EVTEST(Output);
begin
  Writeln(1>0);
end. 

image.png

See also:

比較結果を数値で返したい場合

結果を数値で返したい場合には、論理型を含めた順序型の順序値を返す標準関数 Ord() を使います。Delphi だと Integer(1>0) のようにも書けますが、これは型キャストなので個人的には好きではありません (書かない事もないけれど)。

EVTEST.pas
program EVTEST(Output);
begin
  Writeln(Ord(1>0)); { Return ordinal value }
end. 

image.png

EVTEST.dpr
program EVTEST;
{$AAPPTYPE CONSOLE}
begin
  Writeln(Integer(1>0)); // 型キャスト
end. 

See also:

Pascal の論理型の順序値

Pascal の論理型 (Boolean) は False, True という順序で並んでいるため、

  • False = 0
  • True = 1

となります。Truenot False だから数値で -1 という考え方ではありません。"値で -1" というのは、たとえば 8bit だと not 0b00000000 = 0b11111111 = 0xFF (unsigned) = -1 (signed)という考え方の事です。

「8bit と 16bit の -1 は同じ値なのか?」とか考えだすと、Boolean (bool) 型はあった方がいいよねって結論に至ると思います。

Delphi には他言語との互換性のために ByteBool / WordBool / LongBool という True が -1 の順序値を返す型も用意されています。

See also:

Delphi のビット論理演算

Delphi で特定のビットが立っているのかを調べるのはちょっと面倒です。次のような書き方 (バイトの最上位ビットが立ってるか調べる) ができないのは、and の項 (オペランド) が論理型ではないためビット論理演算となり、結果が項の型 (例の場合 byte) で返るからです。

EVTEST.dpr
program EVTEST;
{$AAPPTYPE CONSOLE}
begin
  if $7F and $80 then // NG
    Writeln('Set')
  else
    Writeln('Not set.');
end. 

Pascal の if 文における評価式は論理式です。式は論理型を返す必要があります。
image.png
Delphi には項 (オペランド) の型によって異なる動作をする演算子があります。ビット論理演算を使って特定のビットが立っているのかを調べるには次のようなコードになります。

EVTEST.dpr
program EVTEST;
{$AAPPTYPE CONSOLE}
begin
  if $7F and $80 = $80 then // OK
    Writeln('Set')
  else
    Writeln('Not set.');
end. 

image.png
もしくは先述の ByteBool / WordBool / LongBool を使います。

EVTEST.dpr
program EVTEST;
{$AAPPTYPE CONSOLE}
begin
  if ByteBool($7F and $80) then // OK
    Writeln('Set')
  else
    Writeln('Not set.');
end. 

ByteBool / WordBool / LongBool は 0 が False、それ以外が True となる型なので、次のような書き方と同じ事になります。

EVTEST.dpr
program EVTEST;
{$AAPPTYPE CONSOLE}
begin
  if $7F and $80 <> 0 then // OK
    Writeln('Set')
  else
    Writeln('Not set.');
end. 

また、Delphi 10.4 では次に示す ビットカウント標準関数 が追加されています。

関数 説明
System.CountLeadingZeros32() パラメータ X で 1 を保持する最上位ビットより上位ビットにある 0 の数を返します。X が 0 の場合、ビット幅を返します。つまり、CountLeadingZeros32 では 32 を返します。
System.CountLeadingZeros64() (同上) CountLeadingZeros64 では 64 を返します。
System.CountTrailingZeros32() パラメータ X で 1 を保持する最下位ビットより下位ビットにある 0 の数を返します。X が 0 の場合、ビット幅を返します。つまり CountTrailingZeros32 では 32 を返します。
System.CountTrailingZeros64() (同上) CountTrailingZeros64では 64 を返します。
System.CountPopulation32() パラメータ X の 1 の数をカウントします。戻り値は、0 からビット幅の数字の範囲になります。つまり、CountPopulation32 では 32 です。
System.CountPopulation64() (同上) CountPopulation64 では 64 です。

非効率ではありますが、次のようなコードも書けるようになった、という事です。

EVTEST.dpr
program EVTEST;
{$APPTYPE CONSOLE}
begin
  if CountPopulation32($7F and $80) <> 0 then
    Writeln('Set.')
  else
    Writeln('Not set.');
end.

2022/09/01 時点では上記ビットカウント標準関数のドキュメントがありません。

See also:

Pascal のビット論理演算

標準 Pascal にはビット論理演算子はありません。つまり、次のような記述はできません。

EVTEST.dpr
program EVTEST(Output);
begin
  if 127 and 128 <> 0 then // NG
    Writeln('Set.')
  else
    Writeln('Not set.');
end.

標準 Pascal では 16 進数を表す事ができないので、10 進数を使っている事に注意してください。

強いて言えば 集合 (Sets) が抽象化されたビット配列です。

SetsTest.pas
program SetsTest(Output);
type
  TBits = (bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7);
var
  a, b: Set of TBits;  
begin
  a := [bit6, bit5, bit4, bit3, bit2, bit1, bit0]; { 0x7F }
  b := [bit7]; { 0x80 }
  if a*b <> [] then { a AND b <> 0x00 }
    Writeln('Set.')
  else
    Writeln('Not set.');  
end.

これでは不便だという事で、Turbo PascalDelphi ではビット論理演算子が追加され、Macintosh 系の Pascal ではビット操作ルーチンが追加されています。

{ MPW Pascal }
BAND()		BOR()		BXOR()		BNOT()
BSL()		BSR()		BRotL()		BRotR()
BTst()		HIWrd()		LOWrd()		BClr()
BSet()
{ THINK Pascal }
BitAnd()	BitOr()		BitXor()	BitNot()
BAND()		BOR()		BXOR()		BNOT()
BSL()		BSR()		BRotL()		BRotR()
BTst()		HiWord()	HIWrd()		LoWord()
LOWrd()		BClr()		BSet()

Pascal の後継言語である Modula-2 には BITSET (ビット集合) 型があり、16進値を示すポストフィクス (H) があります。

See also:

おわりに

この記事のそもそもの元ネタはこちらです。

C 言語の int 型がどういう振る舞いをするのかを当てるクイズです。本記事はこのクイズの問1を Pascal (Delphi) 向けにしたものです。

7
3
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
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?