危険物の指定数量の倍数をClaude Codeで計算し検算する手順
品名ごとの指定数量で保管量を割り、商を合算して1以上かを判定するスクリプトをClaude Codeに書かせ、端数と漢数字の落とし穴を検算で潰す手順。倍数が分かれ目になる確認項目も表にしました。
指定数量の倍数は、品名ごとの貯蔵量を指定数量で割り、その商を足し合わせた値です。合計が1以上なら、その場所は指定数量以上の危険物を扱っているものとして扱われます。計算は小学生でもできますが、品名の取り違えや端数の丸めで判定が逆転します。ここでは、数表の転記・合算・判定をClaude Codeにスクリプトとして書かせ、テストで検算する手順を示します。
例に出す数量は手順確認用の仮の値で、実在の施設のものではありません。
倍数の定義と、検算が要る理由
指定数量は、危険物の規制に関する政令(以下、政令)の第一条の十一が「別表第三の類別・品名・性質に応じた数量」と定めています。ガソリンのような第四類はリットル、第一類などの固体はキログラムが単位です。
倍数の定義は消防法第十一条の四にあります。製造所等で扱う危険物の数量を指定数量で割った値で、品名や指定数量が異なる危険物が複数あるときは、それぞれを割った値の和です。
合算の判定は消防法の第十条第二項が根拠です。品名または指定数量を異にする二以上の危険物を同一の場所で貯蔵・取扱いするとき、それぞれの数量を指定数量で除した商の和が一以上なら、その場所は指定数量以上の危険物を扱っているとみなされます。
計算で間違えやすい三点
- 判定は「1以上」で、ちょうど1.0も該当する
- 品名と水溶性の別で分母が変わる
- 割った商は個別に丸めず、最後に足す
指定数量未満でも無規制になるわけではありません。消防法第九条の四は、指定数量未満の危険物の貯蔵・取扱いの技術上の基準を市町村条例に委ねています。「1未満」は「国の政令の対象外」を意味するだけで、条例の確認が別に残ります。
別表第三をコードにする
第四類だけでも、品名と水溶性の別で分母が10通りに分かれます。別表第三の第四類は次のとおりです。
| 品名 | 性質 | 指定数量(リットル) |
|---|---|---|
| 特殊引火物 | 性質- | 指定数量(リットル)50 |
| 第一石油類 | 性質非水溶性液体 | 指定数量(リットル)200 |
| 第一石油類 | 性質水溶性液体 | 指定数量(リットル)400 |
| アルコール類 | 性質- | 指定数量(リットル)400 |
| 第二石油類 | 性質非水溶性液体 | 指定数量(リットル)1,000 |
| 第二石油類 | 性質水溶性液体 | 指定数量(リットル)2,000 |
| 第三石油類 | 性質非水溶性液体 | 指定数量(リットル)2,000 |
| 第三石油類 | 性質水溶性液体 | 指定数量(リットル)4,000 |
| 第四石油類 | 性質- | 指定数量(リットル)6,000 |
| 動植物油類 | 性質- | 指定数量(リットル)10,000 |
これをClaude Codeに辞書として書かせます。依頼文には、表を貼る代わりに「e-Gov法令検索の政令本文から別表第三を取得して転記する」と書きます。取得した本文との突き合わせまでスクリプトに入れておくと、手入力の転記ミスを避けられます。
from fractions import Fraction
# 危険物の規制に関する政令 別表第三(第四類のみ。単位はリットル)
SHITEI = {
("第四類", "特殊引火物", None): 50,
("第四類", "第一石油類", "非水溶性"): 200,
("第四類", "第一石油類", "水溶性"): 400,
("第四類", "アルコール類", None): 400,
("第四類", "第二石油類", "非水溶性"): 1000,
("第四類", "第二石油類", "水溶性"): 2000,
("第四類", "第三石油類", "非水溶性"): 2000,
("第四類", "第三石油類", "水溶性"): 4000,
("第四類", "第四石油類", None): 6000,
("第四類", "動植物油類", None): 10000,
}
def bairitsu(rows):
"""rows: [(キー, 数量), ...] -> 倍数(Fraction)"""
return sum((Fraction(q) / SHITEI[k] for k, q in rows), Fraction(0))
# 以降の例で使う品名のキー
G = ("第四類", "第一石油類", "非水溶性") # ガソリン
K = ("第四類", "第二石油類", "非水溶性") # 灯油
J = ("第四類", "第三石油類", "非水溶性") # 重油除算に Fraction を使うのは、浮動小数点だと端数が出て「ちょうど1」の判定が崩れるおそれがあるからです。割り算の結果は分数のまま持ち、表示するときだけ小数にします。
漢数字の表を機械で読むときの落とし穴
e-Govの政令本文では、別表の数量が「一、〇〇〇」「一〇、〇〇〇」のように、位取りを漢数字の並びで書く形式です。「一〇」は10で、十を使う表記ではありません。Claude Codeに取得処理を書かせるなら、次の変換を入れ、数値の一致をテストにします。
KANJI = {"〇": 0, "一": 1, "二": 2, "三": 3, "四": 4,
"五": 5, "六": 6, "七": 7, "八": 8, "九": 9}
def kansuji(s: str) -> int:
return int("".join(str(KANJI[c]) for c in s if c in KANJI))
assert kansuji("一、〇〇〇") == 1000
assert kansuji("一〇、〇〇〇") == 10000保管量の一覧から倍数を合算する
保管量はCSVとして渡します。ここでは次の3品目を例にします。
| 品目 | 品名 | 性質 | 数量(L) | 商 |
|---|---|---|---|---|
| ガソリン | 品名第一石油類 | 性質非水溶性 | 数量(L)120 | 商0.60 |
| 灯油 | 品名第二石油類 | 性質非水溶性 | 数量(L)600 | 商0.60 |
| 重油 | 品名第三石油類 | 性質非水溶性 | 数量(L)1,000 | 商0.50 |
CSVを読んで倍数を出す
CSVの列は品目・類・品名・性質・数量です。性質は水溶性の別で、該当しない品名は空欄です。
品目,類,品名,性質,数量
ガソリン,第四類,第一石油類,非水溶性,120
灯油,第四類,第二石油類,非水溶性,600
重油,第四類,第三石油類,非水溶性,1000読み込みと合算は次のとおりです。上の辞書と関数(SHITEI・bairitsu・G・K・J・kansuji)は sq.py に保存しておきます。辞書に無い組み合わせは、推測で埋めずにエラーで止めます。
import csv, sys
from fractions import Fraction
from sq import SHITEI
def main(path):
total = Fraction(0)
for r in csv.DictReader(open(path, encoding="utf-8")):
key = (r["類"], r["品名"], r["性質"] or None)
if key not in SHITEI:
sys.exit(f"未登録の品名・性質: {key}")
term = Fraction(r["数量"]) / SHITEI[key]
total += term
print(f'{r["品目"]} | {r["数量"]} | {SHITEI[key]} | {float(term):.2f}')
print(f"倍数 {total} ({float(total):.2f}) -> "
+ ("1以上" if total >= 1 else "1未満"))
main(sys.argv[1])上のCSVで実行すると、末尾は 倍数 17/10 (1.70) -> 1以上 と出ました。第二石油類の性質を空欄にした行を渡すと 未登録の品名・性質: ('第四類', '第二石油類', None) で止まります。第二石油類は水溶性か非水溶性かで分母が倍違うため、空欄を許さない設計です。
3品目とも単独では1未満なのに、合算すると超えます。この例が、品名ごとに見て安心してはいけない理由です。
境目のケースも確認します。ガソリン100L(0.5)と灯油500L(0.5)なら商の和はちょうど1で、判定は「以上」になります。
t = bairitsu([(G, 120), (K, 600), (J, 1000)])
print(t, float(t), "指定数量以上" if t >= 1 else "指定数量未満")倍数が分かれ目になる確認項目
倍数は、許可申請書に書く項目であり、施設の基準が切り替わる境目でもあります。政令第六条は、設置許可の申請書に貯蔵・取扱いする危険物の類・品名・最大数量と、指定数量の倍数を記載するよう定めています。計算結果は、この欄にそのまま使える形で出しておくと後工程が楽です。
倍数の値で切り替わる主な項目を、政令の条文から拾うと次のとおりです。
| 施設・項目 | 倍数の境目 | 内容 | 根拠 |
|---|---|---|---|
| 製造所の保有空地 | 倍数の境目10以下 / 10超 | 内容空地の幅3m以上 / 5m以上 | 根拠政令第九条 |
| 屋内貯蔵所の保有空地 | 倍数の境目5以下から200超まで6区分 | 内容区分ごとに幅が増える | 根拠政令第十条 |
| 製造所の避雷設備 | 倍数の境目10以上 | 内容総務省令で定める避雷設備(安全上支障がない場合を除く) | 根拠政令第九条 |
| 警報設備 | 倍数の境目10以上 | 内容総務省令で定めるものは火災報知設備その他の警報設備を設置 | 根拠政令第二十一条 |
| 販売取扱所 | 倍数の境目15以下 / 15超40以下 | 内容第一種 / 第二種 | 根拠政令第三条 |
| 危険物の施設保安員 | 倍数の境目100以上(製造所・一般取扱所) | 内容総務省令で定めるものを除く | 根拠政令第三十六条 |
屋内貯蔵所の保有空地は、倍数が上がるほど広がります。政令第十条の表は次のとおりです。
| 倍数の区分 | 壁・柱・床が耐火構造 | それ以外 |
|---|---|---|
| 5以下 | 壁・柱・床が耐火構造(記載なし) | それ以外0.5m以上 |
| 5超10以下 | 壁・柱・床が耐火構造1m以上 | それ以外1.5m以上 |
| 10超20以下 | 壁・柱・床が耐火構造2m以上 | それ以外3m以上 |
| 20超50以下 | 壁・柱・床が耐火構造3m以上 | それ以外5m以上 |
| 50超200以下 | 壁・柱・床が耐火構造5m以上 | それ以外10m以上 |
| 200超 | 壁・柱・床が耐火構造10m以上 | それ以外15m以上 |
倍数が5.0ちょうどなら「5以下」の行、5.01なら次の行です。境目の判定に、前述の Fraction の比較がそのまま使えます。
許可等の通報の対象も倍数で決まります。政令第七条の三は、倍数10以上の製造所、150以上の屋内貯蔵所、200以上の屋外タンク貯蔵所、100以上の屋外貯蔵所、10以上の一般取扱所などを挙げています。
この表は、倍数から「確認すべき項目の一覧」を出すための種として使えます。個別の免除や総務省令の細目は条文に当たる必要があり、判断は許可を出す市町村長等の側にあります。表の項目は網羅ではなく、倍数を条件にした条文の例です。
Claude Codeに任せる範囲と、検算の仕掛け
役割を分けると、迷いが減ります。
スクリプトと人の役割分担
Claude Codeに任せる
数表の転記と本文との突き合わせ、CSVの読み込み、商の合算、境界値のテストの作成を担当させます。
人が決める
品名の判定(引火点など)、水溶性か非水溶性か、「同一の場所」の範囲、許可の要否の最終判断です。
CLAUDE.mdには、次のような断片を置いておくと、毎回の依頼で前提が揃います。
## 危険物の倍数計算
- 指定数量は政令別表第三の値を使う。e-Gov取得結果と一致するテストを必ず通す
- 割り算は fractions.Fraction。floatで丸めない
- 判定は「商の和が1以上」。1.0ちょうども該当
- 品名・水溶性が不明な行は計算せず、ユーザーに確認する検算が通るまで作業を終えさせない方法として、Stopフックでテストを走らせる構成があります。設定の書き方は、Claude Codeのagent hookでテスト通過まで止めない設定で詳しく扱っています。固定長データを作って桁や合計を検算する流れは、全銀フォーマットの総合振込データの記事と同じ考え方です。
テストは、法令の数値を直接検証する形にします。
from fractions import Fraction
from sq import SHITEI, bairitsu, kansuji, G, K, J
def test_matches_law_text():
# 政令本文の漢数字を kansuji で読んだ値と辞書が一致する
assert SHITEI[G] == kansuji("二〇〇")
assert SHITEI[K] == kansuji("一、〇〇〇")
assert SHITEI[J] == kansuji("二、〇〇〇")
def test_example():
assert bairitsu([(G, 120), (K, 600), (J, 1000)]) == Fraction(17, 10)
def test_boundary_is_inclusive():
assert bairitsu([(G, 100), (K, 500)]) == 1上の3本は、手元で実行して通りました。Claudeの数値処理そのものの精度については、Claude数式・計算の精度と検算が必要な理由にまとめています。
許可済みの倍数との突き合わせ
計算した倍数は、新規の申請だけでなく、すでに許可を受けた施設の運用チェックにも使えます。政令第二十四条の通則は、許可・届出に係る品名以外の危険物や、許可・届出に係る数量または指定数量の倍数を超える危険物を、製造所等で貯蔵・取扱いしないよう定めています。
位置・構造・設備を変えないまま、品名・数量・倍数を変更する場合の届出は、消防法第十一条の四が根拠です。変更しようとする日の十日前までに市町村長等へ届け出ます。この条文の倍数も、品名や指定数量が異なるときは商の和で定義されています。
月次の在庫一覧から倍数を出し、許可書に書かれた倍数と比べるスクリプトも、同じ関数で書けます。比較対象は次の3点です。
- 在庫一覧にある品名が、許可の品名に含まれているか
- 倍数の合計が、許可された倍数以下か
- 倍数が増える入荷計画が、変更届を要する変更に当たらないか
三つ目は計算では決まらないため、スクリプトは「届出の確認が必要」という警告を出すところまでにとどめます。許可書の倍数は、手入力せずにCSVの別列から読ませると、転記ミスが減ります。
判定を誤りやすい場面
品名はスクリプトの外で決まる
第一石油類は引火点21度未満、第二石油類は21度以上70度未満、第三石油類は70度以上200度未満、第四石油類は200度以上250度未満と、消防法別表第一の備考が定めています。引火点の実測値や製品のSDSから品名を選ぶ部分は、人が確認した入力としてCSVに入れます。塗料類などで総務省令により除外されるものもあるため、Claudeには品名を推定させず、人が確認した値を入力にします。
水溶性の判定にも定義がある
備考は、水溶性液体を「1気圧、20度で同容量の純水と緩やかにかき混ぜ、流動がおさまった後も混合液が均一な外観を維持するもの」と定めています。品名の欄に「水溶性」と書いてあっても、製品名だけでは決まりません。
第三石油類以降は「20度で液状」が前提
消防法別表第一の備考は、第三石油類・第四石油類・動植物油類を、1気圧・20度で液状のものに限っています。
数量はタンクの内容積ではない
政令第五条は、タンクの容量を内容積から空間容積を差し引いた容積としています。容器の表示容量ではなく、実際に貯蔵・取扱いする数量を入力にします。
同一の場所の範囲
合算は「同一の場所」で行うため、建物や区画の切り分けで結果が変わります。範囲の判断はスクリプトで決められません。
運搬にも同じ合算が及ぶ
政令の運搬の基準にも、複数の危険物を運ぶときに商の和が1以上なら指定数量以上を運搬しているとみなす規定があります。貯蔵向けの計算と同じ関数を流用できます。
次に足すと役立つ拡張
第四類以外も扱うなら、別表第三の残りの行(第一類から第六類まで)を同じ辞書に追加し、単位をキログラムとリットルで分けて持たせます。単位の違うものを同じ列で足さないよう、キーに単位を持たせてテストで確かめます。
別表第三の備考には、第一種・第二種の酸化性固体や可燃性固体の定義が試験の結果に基づいて書かれています。試験結果に依存する分類は、品名の判定と同様に人が確定した値を入力にします。
指定可燃物は別表第四の数量で扱われ、危険物の指定数量とは別の表です。同じ関数に混ぜず、表を分けて持つと取り違えを防げます。