1割る3が割り切れる

0.33333・・・割り切れないよ、書ききれないよ!

はじめに

高校1年の数学の授業で有理数無理数の概念を学習します。 そのうち、円周率パイや平方根ルートが無理数と教えられます。 円周率など、「3.14159・・・」といつまでも数字がつづく終わりがない数字と理解しているでしょう。

分数を小数化したとき、割り切れない場合、循環小数となります。 循環小数無理数と同じく、いつまでも数字が続いていきます。 にもかかわらず、有理数でひとくくりなんです。 なぜでしょう? ここでは、それをネタにお話しします。

柱脚:ここでの割り切れるとは、小数が循環せずに書ききれる事を意味します。

1は3で割り切れない

さて、分数も同じように数字が終わらない場合があります。 三分の一なら、「0.33333・・・」と同じように3が延々と続く数字です。 しかし、これは有理数として教えられます。

1割る10(つまり十分の一)は、0.1となり割り切れます。 1割る3(つまり三分の一)は、0.3333...となり割り切れません。 あたりまえ? いえいえ、当たり前にもいろいろ面白いことがあるのです。

結論から言うと、割り切れるとか割り切れないとかは、私たちの都合で勝手に区別しているだけなのです。 もしかしたらこの宇宙には、1が3で割り切れると考える世界があるかもしれないのです。

十進数と三進数

高校で有理数無理数の概念と同じ頃に、10進数という概念も学習します。

私たちは、一桁を0から9までの十種類の文字で表します。 十を示すには桁上がりを利用して、2つの文字を使って10と表します。 十で桁が上がるので、十進数といわれるのでしょう。 手の指は10本あるしね。

    0,1,2,3,4,5,6,7,8,9 -> 桁上がり 10

さあ、数学の面白いところです。 十進数があるんだったら、三進数もあっていいんじゃね? イエス!数学的にはアリです。 十進数と同じように考えればいいんです。

一桁を0から2までの三種類の文字で表します。 三を示すには桁上がりを利用して2つの文字を使って10と表します。 三で桁が上がるので、三進数ですね。 きっと、高度に発達した三本触手の宇宙人の世界でしょう。

    0,1,2 -> 桁上がり 10,11,12 -> 桁上がり 20

まだ続きますよ~。

1が3で割り切れる世界

私たち十進数の世界の数は、次の様に書くことができます。

  100     1の10倍の10倍
   10     1の10倍
    1     1
    0.1   1の10分の1
    0.01  1の10分の1の10分の1
    0.001 1の10分の1の10分の1の10分の1

同様に、三本触覚宇宙人の三進数の世界の数のは次の様に書けます。

  100     1の3倍の3倍
   10     1の3倍
    1     1
    0.1   1の3分の1
    0.01  1の3分の1の3分の1
    0.001 1の3分の1の3分の1の3分の1

わかりますか? 数学では、考え方をとても簡単にどこまでも広げていくことができます。 同じように解釈すればよいだけなのですから。

三進数の世界の人たちにとって、1割る3(三分の一)は単純に0.1と書けちゃいます。 三分の一が割り切れないのは、十進数の世界に住む私たちの都合です。 十進数だから、書ききれないというだけなのです。

どおです?面白くないですか。

2進数の世界、コンピューターの世界

ここまでは想像の三進数世界でしたが、これからは、実社会で問題になりうる事を話します。

進数によって、表現できるできないがあることを話しました。 小学生の時は、割り切れないときは小数第3位で四捨五入しなさいなどの指示があったはずです。 つまり、表現しきれない場合は、近い値でヨロシクしなさいというわけです。

コンピュータは数値を二進数で扱います。 電気信号のオンとオフに起因します。 人間が十進数で与えた数字は、内部で二進数に変換され計算されます。 十進数でも循環小数があるように、当然、二進数でも循環することがあります。 そして、十進数では簡単に表現される小数が、二進数では表現しきれない場合があるのです。

コンピュータといえども、無限に続く循環小数を扱いきれるものではありません。 そんな数値をコンピュータ内では、一般には切り捨て、場合によって四捨五入や切り上げを行い、できうる限り近い数で扱おうとします。 このような処理を「丸め」といい、丸めにより発生する数値の違いを「丸め誤差」と呼んでいます。

お金を扱うようなプログラムの場合、1円の違いも許されません。 循環小数は扱いませんし、割り切れない場合の端数も厳密に扱います。 また二進数変換せずに十進数に近い計算方法が採用されいたりします。 しかし、表計算ソフトなどは厳密でない事が多いので、注意が必要です。

また、学術計算など、当然のように無理数も扱います。 有効桁数を意識し、誤差の範囲を最小限にするような計算方法を取る努力が、欠かせないのです。

まとめ

進数のもとになる数を「基数」と呼びます。 十進数であれば基数は10、二進数であれば基数は2となります。 割り切れるか、循環小数になってしまうかは、基数の取り方によって変わってしまいます。

そして、割り算の結果が書ききれない数字だとしても、それを上手に使える道具を持っています。 道具の名前は?ご存じ「分数」です。 分数を使えば、割り切れない数も、いとも簡単(?)にあつかえます。 一般的にコンピューターは分数を扱えないので、誤差を含む近似値にならざるを得ないのです。

書けるか書ききれないか、小数が循環するかしないか・・・ そんな事は、数値表現による制約であるだけで、数学的に差はなく有理数としてひとくくりにしてよさそうですね。

参考

乱筆

この記事のきっかけは、、、

高1年の教科書をみる機会があり、有理数無理数の概念説明があった。
有理数か・・・循環小数って面白いよな・・・とか。
循環小数の分数化なんてあったよなぁ・・・とか。

すると、割り切れるって、どういう意味だっけ?と疑問がわく。

偶数は2で割れるとか10でなら必ず割り切れるよな・・・モヤモヤと考えていた。
アレレ?3で割るのと10で割る・・・数字が違うだけで、数学的には同じだよなぁ。
と、考えてると、あぁそうか、10進数、基数が10だから絶対割り切れるんだよな。
基数が3なら、ぜったい3で割り切れる・・・モヘェ。

では、何が違うかといえば、表現できるか出来ないかダケ、と思い至ったわけである。
循環小数の循環部の表現方法もあるにはあるが、便宜上の物で、優れた数学表記には思えないし。

そんなとき、とある旅行に使うため、グーグルマップから経路データを引っ張ってきた。
グーグルマップの地点データは、緯度経度で示されていて、360を最大とする小数5桁を含む10進度数法で示されていた。
これから主要地点や全行程の距離を算出すべく、地上のXY直交データに変換する方法を探す。
国土地理院のHPに、オンラインで変換してくれるサービスがあるのだが、要求されるデータが3600000を最大値とする小数4桁を含む度分秒法で示さねばならなかった。
角度にして1度未満は、60進法の分と秒に変換だ。
データは2000程度なので、表計算ソフトを使って変換させたのだが、そこで丸め誤差にしてやられる。
秒単位に数値60が発生していた。
60進法なので取っていい値は0から59。

まぁ、大した話ではないのだが、基数でかけ割りしたり、整数化に関数INT()を使っていたので、さもありなんという話。

学校でBCDとか習ったけど、何に使うんそれ?だったなぁ。
COBOLって素晴らしい・・・しらんけど、という余談もw

以上

免責事項

  • 本記事によって起きたいかなる損害に対し、筆者は責任を負うことはできません。

執筆者備考

2024/04/05 初稿

権利表示

Copyright (C) 2023,2024 upsndownsjp, All Right Reserved.

漢字キーを無効化するプログラム

はじめに

パソコンゲームやってると「漢字」キーを押して操作不能になって困るんです、 なんてことありませんか?「ESC」キーに近すぎ!漢字キーは使わないし無効にできたらいいよね。 っていうことで・・・ここでは漢字キーの無効化だけをできるだけ簡単に紹介します。

対象読者

  • ウィンドウズを操作するプログラムを書いてみたい方
  • Visual Studioがインストールされていること
  • ノートパッドが使えること

プログラムを書きながら、コンピュータの仕組みを知るのは楽しいものです。 コンピュータ好き、ゲーム好き、自分でツールを作ってみたい、 そんな方の参考になれば幸いです。

サンプルコード

それでは、早速サンプルコードを見てください。 ファイルはたったの一つだけ!

sample.cpp

#include <windows.h>
#include <stdio.h>

HHOOK hook; // キーボードフックハンドラー

LRESULT CALLBACK proc(int code, WPARAM wp, LPARAM lp)
{
    KBDLLHOOKSTRUCT *info; // キーボード情報へのポインタ
    int vk;                // バーチャルキーコード

    // 無効フックを除外
    if( code < 0 )
        return CallNextHookEx(hook, code, wp, lp);

    // パラメータを解析
    info = (KBDLLHOOKSTRUCT*)lp;
    vk = (*info).vkCode;

    // 漢字キーを無効にする
    if( (vk==0xF3||vk==0xF4) && wp==WM_KEYDOWN ) {
        putchar('*');  // コメ印を表示
        return 1;      // フックチェーンを破棄
    }

    // フックチェーンの継続
    return CallNextHookEx(hook, code, wp, lp);
}

void main(void)
{
    // キーボードをフックする
    hook = SetWindowsHookEx(WH_KEYBOARD_LL, proc, 0, 0);

    // メッセージループを開始
    MSG msg;
    while( GetMessage(&msg, NULL, 0, 0) ) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

キー入力を無効にするには、「グローバルフック」という手法が必要になります。 グローバルフックで検索をかければ、様々なWEBページで紹介されていることがわかります。 それほどよく知られた手法なのですが、その多くはDLLプログラムとメインプログラムの 2つのファイルを必要とする手法です。 また、動作記述がDLL内部で行われていたりと、複雑な記述がほとんどです。 ウィンドウスアプリケーションの仕様上で仕方ないことなのです。

しかし、コンソールアプリケーションに限定すれば、DLLが必要ありません。 つまり一つのファイルで済みます。記述するのはメイン関数と動作記述部の2つの関数だけです。 私が知りうる限り、最も簡単なグローバルフックのサンプルになるのではないでしょうか。

作業手順

とても簡単!説明も楽チン!

スト2コマンドプロンプトの作業状況を示します。 入力は4カ所だけ。入力する部分を赤色で囲ってありますので参考にしてください。

Developer Command Prompt for VS 2022

**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.5.1
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
C:\Program Files\Microsoft Visual Studio\2022\Community>cd C:\Users\You\Desktop\work↵

C:\Users\You\Desktop\work>cl sample.cpp user32.lib↵
Microsoft(R) C/C++ Optimizing Compiler Version 19.35.32215 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

sample.cpp
Microsoft (R) Incremental Linker Version 14.35.32215.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:sample.exe
sample.obj
user32.lib

C:\Users\You\Desktop\work>sample↵
********^C
C:\Users\You\Desktop\work>

エンターの入力「↵」マークは表示されません。 「\」は、環境によって円マーク「¥」またはバックスラッシュ「\」で表示されています。 いずれも¥キーで入力できるはずです。

プログラムの開発には、GUIで作られた統合環境(IDE)が強力で効率的です。 しかし、作業手順の説明は複雑になりがちで、設定を間違うと沼にはまります。 ここでは、コマンドプロンプトで作業します。 コマンドを手で入力する必要がありますが、とても簡単なのでチャレンジしてみてください。

手順1.作業フォルダを作ります

デスクトップでマウスを右クリックし、「新規作成」次に「フォルダ」を選びます。 新しいフォルダーの名前を「work」に変更してください。

手順2.ソースファイルを作ります

ノートパッドを開き、リスト1をコピペします。 次に、名前をつけて保存をします。

  • フォルダは先ほど作ったデスクトップ上のworkを指定。
  • 文字コードANSIで指定。
  • ここではファイル名を「sample.cpp」とします。
手順3.コマンドプロンプトを開きます

ここでは、2022年度版のコミュニティーエディションを使っています。 コミュニティーエディションは規約を守ることで無償で使うことができます。

スタートメニューから「Visual Studio 2022」内の 「Deveropper Command Prompt for VS 2022」を開きます。 開かれた窓をクリックして次からのコマンド入力の準備が整います。

手順4.作業フォルダに移動

コマンド cd C:\Users\You\Desktop\work を入力し、作業フォルダに移動します。

例ではユーザー名「You」のデスクトップにフォルダ「work」を作っています。 Youの部分は、環境によって変わりますのであなたの環境に合わせて置き換えてください。

手順5.ビルド

ビルドとは実行ファイルを作成することです。 コマンド cl sample.cpp user32.lib を入力します。 cl は実行ファイルを作成するコマンドで、コンパイルとリンクの略だと思われます。 user32.lib は、今回のビルドに必要なファイルでライブラリと呼ばれています。 うまくいけば実行ファイル sample.exe が作成されているはずです。 なお sample.obj は、中間ファイルという作業ファイルの一つで削除しても問題ありません。

手順6.実行

コマンド sample を入力します(sample.exeでもよい)。 実行中に漢字キーを押すと「*」マークが表示されるはずです。 ノートパッドなどを開いて漢字の入力を試してみてください。 漢字の入力ができなければ成功です。

手順7.終了

コマンドプロンプトを選んでから、^Cを入力します。 組み合わせキー入力で、Ctrlキーを押したままCキーを押すことを示します。

お疲れさまでした!

うまくいかないときは

  • ファイルの文字コードANSIですか?UTF-8になってませんか?
  • VisulaStudio開発用のプロンプトで作業してますか?
  • WindowsやVisualStudioは標準的にインストールされていますか?

用語

イベントとかプロシージャとかフックとかとかとか

ウィンドウズは、アプリケーションをメッセージという仕組みを使って制御しています。 特定のメッセージが発生した時をイベント(event)と呼びます。 イベント発生時に実行する動作を一般的にプロシージャ(procedure)といい、 ユーザーが定義する場合、定められた形式のコールバック関数で記述する必要があります。 コールバック関数を登録しておくことをフック(hook)するといいます。

ローカルフックとグローバルフック

一般的なウィンドウズアプリケーションは自身へのイベントだけしか取得できません。 自身へのイベントの取得を単にフック、区別するならローカルフック(local hook)と呼びます。 これに対して、自分以外のアプリケーションのイベントやシステム全体に渡るイベントにフックする事を グローバルフック(global hook)と呼びます。 グローバルフックを使うことで、他のアプリケーションに送られるイベントを先取りできるようになります。 プログラマが記述したプロシージャによって、他のアプリケーションへの入力を阻害したり、 用意した別の処理を行わせたりすることができるようになるのです。

一般的なウィンドウズアプリケーションでは、グローバルフックを実現するためにDLLを用意します。 DLLをロードするとDLLインスタンスが得られ、 DLLインスタンスを使うことで、システム全体のメッセージをフックできるようになります。 そして、ここで紹介したようにコンソールアプリケーションでは、DLLなしで同様な動作ができるのです。

キーボードの入力メッセージをフック

ここでは「低レベルのキーボード入力」と呼ばれるイベントをグローバルフックしています。 フックは SetWindowsHookEx 関数によって行われ、ID は WH_KEYBOARD_LL を使います。 IDを変えることで、例えばマウスの動作など様々なメッセージに対応できます。 戻り値(HHOOK hook)はメイン関数とコールバック関数で必要なため、グローバル変数にしました。

コールバック関数は、LowLevelKeyboardProc に示された仕様に厳密に従います。 システムで管理されていますので、その点はユーザーの自由に作れる関数と異なります。 関数名は自由なので短く proc としています。

参考ページ:

最後に

蛇足だけど・・・ グローバルフックは、システムを監視する基本的な仕組みで、ハッキングにも使われます。 例えば、キー入力の監視は、パスワードを盗んだりすることに利用できちゃいそうです。 もしかしたら、マルウエア監視にひっかかるかもしれませんね。 でも自分で作ったプログラムなら無視して大丈夫。

また、オンラインゲームなどはチートを防ぐために、 このような自動化に類似したプログラムが動作しているかどうかを監視してるかもしれません。 ずるしちゃダメですよ(笑)。

おことわり

  • 本記事によって起きたいかなる損害に対し、筆者は責任を負うことはできません。
  • ご自身の趣味の範囲を超えた責任のあるプログラムへの利用はご遠慮ください。
  • このコードには実行時に起こりうるシグナルやエラーを処理していません。
  • このコードには本来行うべき終了時の処理が記述されていません。

執筆者備考

2024/01/07 初稿。下書きから1年もかかったw

権利表示

Copyright (C) 2023,2024 upsndownsjp, All Right Reserved.

はてな記法の練習

このページは、はてな記法で記述されています。

はてな記法の練習

はてな記法は、一種のマークダウン方式です。HTMLタグも書き込むことができます。しかし、HTMLタブが表示されなくなり、純粋なHTML編集ができなくなります。編集ページではリアルタイムプレビューにより、書式の見た目を確認しながら編集できます。しかし、デザインテーマなどとの相性もあるので実際の表示と体裁が必ずしも一致するとは限りません。むしろ、デザインテーマの調節が必要になるかもしれません。

書式

書式には大中小見出しと標準が用意されています。

見出しのマークにはアスタリスク(いわゆるコメ印)が用いられます。その個数によりHTMLの<h3>から<h5>に変換されます。IDにはタグ内の文字が使われ、目次のページ内ジャンプに使われます。

標準行(マークのない行)は、HTMLの<p>に返還されます。改行は<br>に変換され同一のパラグラフとして扱われます。空白行を挿入することで次のパラグラフに分けられます。


はてな記法変換されるHTML見ため
* 大見出し <h3 id="???">大見出し</h3>

大見出し

** 中見出し <h4 id="???">中見出し</h4>

中見出し

*** 小見出し <h5 id="???">小見出し</h5>
小見出し

標準行1
標準行2

標準行3

<p>標準行1<br>標準行2</p>
<p>標準行3</p>

標準行1
標準行2

標準行3

箇条書き

行頭にハイフンまたはプラスで記述。入れ子として記述したい場合は、マークを複数個つなげて記述します。




はてな記法変換されるHTML見ため

- 箇条書き1
- 箇条書き2
-- 箇条書き2の子
--- 箇条書き2の孫

<ul>
  <li>箇条書き1</li>
  <li>箇条書き2</li>
  <ul>
    <li>箇条書き2の子</li>
    <ul>
      <li>箇条書き2の孫</li>
    </ul>
  </ul>
</ul>

  • 箇条書き1
  • 箇条書き2
    • 箇条書き2の子
      • 箇条書き2の孫




はてな記法HTMLプレビュー

+ 箇条書き1
+ 箇条書き2
++ 箇条書き2の子
+++ 箇条書き2の孫

<ol>
  <li>箇条書き1</li>
  <li>箇条書き2</li>
  <ol>
    <li>箇条書き2の子</li>
    <ol>
      <li>箇条書き2の孫</li>
    </ol>
  </ol>
</ol>

  1. 箇条書き1
  2. 箇条書き2
    1. 箇条書き2の子
      1. 箇条書き2の孫

目次

目次は、単独行に[:contents]と書くと見出しを拾って箇条書きで構成します。前後に文字や空白を入れてはならない。はてな記法によって与えられたアスタリスク1から3個で与えられた見出しや、HTMLタグで直接与えた<h3>から<h5>を自動的に解析して目次を表示します。






はてな記法 HTML
[:contents]

<ul class="table-of-contents">
    <li><a href="#はてな記法の練習">はてな記法の練習</a><ul>
            <li><a href="#書式">書式</a></li>
(・・・省略・・・)


見た目

スーパーpre記法

スーパーpre記法は、タグや空白、改行などの本来エスケープしなければならない文字をそのままに表示できるよう変換してくれる記述方式です。スーパーpre記法は>||||<で囲みます。各言語の色付き表示は、>|言語名|||<で囲みます。



はてな記法HTML見た目
>|c|
#include<stdio.h>
int main(void)
{
    printf("Hello World\n");
}
||<

<pre
    class="code lang-c"
    data-lang="c"
    data-unlink=""
>
        (コード)
</pre>

#include<stdio.h>
int main(void)
{
    printf("Hello World\n");
}

引用

書籍や他者のWEBページなどから転載する時に使われる書式です。引用は、<<>>で囲み、HTMLの<blockquote>で置き換えられます。内部文書は標準書式に準拠するようです。自動でボタンが配置され、押すことで引用文書がクリップボードにコピーされます。

引用を記述するとページの先頭に引用が自動的に挿入されるが、削除することもできます。




はてな記法HTML見た目

>>
引用1行目
引用2行目

引用3行目
<<

<blockquote>
  <p>引用1行目<br>引用2行目</p>
  <p>引用3行目</p>
  <div class="requote-button js-requote-button">
    <button class="requote-button-btn tipsy-top"
      original-title="引用する">
      <i class="blogicon-quote"></i>
    </button>
  </div>
</blockquote>

引用1行目
引用2行目

引用3行目

文字の装飾

はてな記法では、文字の装飾の為のマークは用意されていません。文字や文書を選択しGUIのボタンを押すことで即座にHTMLに変換されます。斜体は<em>に変換されますが、テーマによっては斜体にならないことがありました(汗。デザインテーマによる調整が必要かもしれません。




はてな記法HTML見た目

なし

<strong>太字</strong>
<em>斜体</em>
<s>打消</s>
<u>アンダーライン</u>
<span style="font-size: 150%">文字の大きさ中(150%)</span>
<span style="color: #cc00cc">文字色ムラサキ</span>


太字
斜体
打消
アンダーライン
文字の大きさ中(150%)
文字色ムラサキ

表組

編集ページには表組を作成するためのGUIは用意されていません。しかし、縦棒とアスタリスクの組み合わせで票組を作成することができます。





はてな記法HTML見た目

| |*A|*B|*C|
|*1|A1|B1|C1|
|*2|A2|B2|C2|
|*3|A3|B3|C3|

<table><tbody>
  <tr>
    <td></td><th>A</th><th>B</th><th>C</th>
  </tr>
  <tr>
    <th>1</th><td>A1</td><td>B1</td><td>C1</td>
  </tr>
  <tr>
    <th>2</th><td>A2</td><td>B2</td><td>C2</td>
  </tr>
  <tr>
    <th>3</th><td>A3</td><td>B3</td><td>C3</td>
  </tr>
</tbody></table>

A B C
1 A1 B1 C1
2 A2 B2 C2
3 A3 B3 C3

リンクは

アイコンの挿入は

  • はてなブログの組み込みアイコン <span class="blogicon-good"/>
    • blogicon-good


みたまま編集(HTML編集)の練習


HTML編集の練習

見出し

ここは本文。

コードの貼り付けは

<pre><code>を使う。カギ括弧などHTMLにしたがって書き換える必要があるので記述が煩雑になる。

#include<stdio.h>
int main(void)
{
    printf("Hello World.\n");
}

コードの貼り付けは

マークダウン編集の練習


マークダウン記述の練習

1

見出し

###大見出し

####中見出し

#####小見出し

標準 ここは本文

コードの貼り付けは

```cを使う。はてなブログでは```c:<filename>は使えない。

#include<stdio.h>
int main(void)
{
    printf("Hello world.\n");
}