Pythonで学ぶSQLite浮動小数点数:コード例で徹底解説

2025-06-06

SQLiteは、他の多くのデータベースシステムと同様に、数値を格納するためにいくつかのデータ型をサポートしています。その中で「浮動小数点数」は、小数点以下の値を持つ数、つまり実数を表現するために使用されます。

SQLiteでは、浮動小数点数を格納するための特定のデータ型として「REAL」があります。

REALデータ型とは

  • NULL値: 他のSQLiteのデータ型と同様に、REALカラムもNULL値を格納できます。
  • 丸め誤差: 浮動小数点数の性質上、REAL型で表現できるのは、有限の精度を持つ近似値であることに注意が必要です。特に、10進数で正確に表現できる一部の数(例: 0.1, 0.2など)は、2進数の浮動小数点数として格納される際にわずかな丸め誤差が生じることがあります。このため、浮動小数点数の厳密な等値比較(=)は避けるべきであり、代わりに範囲での比較(><BETWEENなど)や、わずかな許容範囲(epsilon)内での比較を使用することが推奨されます。
  • 精度: REAL型は通常、倍精度浮動小数点数として実装されており、約15桁の10進数の精度を提供します。これは、ほとんどの一般的な用途で十分な精度です。
  • 定義: REALは、8バイトのIEEE浮動小数点数として格納されます。これは、非常に大きな範囲の数と、小数点以下の精度を必要とする数(例えば、科学的な測定値、通貨の値、地理座標など)を扱うのに適しています。

浮動小数点数の使用例

以下は、SQLiteでREAL型のカラムを持つテーブルを作成し、データを挿入・クエリする例です。

-- テーブルの作成例
CREATE TABLE products (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    price REAL
);

-- データの挿入例
INSERT INTO products (name, price) VALUES ('Laptop', 1200.50);
INSERT INTO products (name, price) VALUES ('Mouse', 25.99);
INSERT INTO products (name, price) VALUES ('Keyboard', 75.00);
INSERT INTO products (name, price) VALUES ('Monitor', 350.75);

-- データのクエリ例
SELECT name, price FROM products WHERE price > 100.00;

-- 浮動小数点数の計算例
SELECT name, price * 1.10 AS price_with_tax FROM products;

注意点

  • TEXTとしての格納: まれに、特に意図しない変換を防ぐために、浮動小数点数をTEXT型として格納するアプローチが取られることもありますが、これは通常、計算を行う場合には不便であり、推奨されません。正確な計算が必要な場合は、REAL型を使用し、上記で述べた丸め誤差に注意を払うか、あるいは通貨などの場合は、整数型で最小単位(例えば、セント)を格納する方法も検討されます。
  • データ型のアフィニティ: SQLiteは「宣言された型」ではなく「データ型のアフィニティ」という概念を使用します。これは、REALとして宣言されたカラムに、実際には整数値が挿入されても、SQLiteがそれを自動的に浮動小数点数として扱う(または必要に応じて変換する)ことを意味します。例えば、priceカラムに100を挿入すると、それは100.0として格納されます。


丸め誤差による比較の失敗

これが最も一般的で、理解しておくべき重要な点です。浮動小数点数は、2進数で表現されるため、10進数で正確に表せると思っていた数値でも、内部的にはごくわずかな誤差を持つ近似値として格納されることがあります。

問題の例
データベースに 0.1 を挿入したつもりでも、実際には 0.10000000000000000555 のような値として格納されることがあります。 このため、WHERE price = 0.1 のような厳密な等値比較を行うと、意図しない結果になることがあります。

-- テーブル作成
CREATE TABLE items (
    id INTEGER PRIMARY KEY,
    value REAL
);

-- データ挿入
INSERT INTO items (value) VALUES (0.1);
INSERT INTO items (value) VALUES (0.2);
INSERT INTO items (value) VALUES (0.3);

-- 厳密な等値比較の失敗例
SELECT * FROM items WHERE value = 0.1; -- 期待通りに動作するかもしれないが、他の値では失敗する可能性あり
SELECT * FROM items WHERE value = 0.3; -- 0.3は2進数で正確に表現できないため、マッチしないことが多い

トラブルシューティング/解決策

  • 特定の関数を使用する(非標準的)
    SQLiteには直接的なDECIMAL型がないため、拡張機能やアプリケーション側での処理が必要になる場合があります。printf関数を使って、小数点以下の桁数を指定して比較対象の値を文字列に変換し、比較するというトリッキーな方法も考えられますが、パフォーマンスや正確性の観点から推奨されません。

  • 整数型で格納する(通貨など)
    特に通貨のような正確な計算が求められるデータの場合、浮動小数点数を使用するのではなく、最小単位(例:円、セント)を整数型で格納することを検討します。 例えば、12.34ドルを1234セントとして整数型で保存します。

    CREATE TABLE products (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        price_in_cents INTEGER -- 価格をセント単位で整数として格納
    );
    
    INSERT INTO products (name, price_in_cents) VALUES ('Laptop', 120050); -- 1200.50ドル
    

    これにより、丸め誤差の問題を完全に回避できます。表示や入力の際に変換処理が必要になりますが、計算の正確性が保証されます。

  • 範囲比較を使用する
    厳密な等値比較の代わりに、数値の範囲で比較します。

    SELECT * FROM items WHERE value > 0.2999999999 AND value < 0.3000000001;
    -- または
    SELECT * FROM items WHERE value BETWEEN 0.2999999999 AND 0.3000000001;
    

    この方法は、許容できる誤差の範囲を設定することになります。

データの表示における精度問題

アプリケーション側でSQLiteからREAL型の値を取得し、それを表示する際に、期待通りの桁数で表示されないことがあります。

問題の例
12.34と格納したつもりが、アプリケーションで表示すると12.340000000000001のように余計な桁が表示される。

トラブルシューティング/解決策

  • SQLのROUND()関数を使用する
    SQLiteのROUND()関数を使って、クエリ時に丸めることもできます。

    SELECT name, ROUND(price, 2) AS rounded_price FROM products;
    

    ただし、これにより格納されている実際の値が変わるわけではないことに注意してください。あくまで表示上の丸めです。

  • アプリケーション側で丸める
    取得した値をアプリケーションのプログラミング言語の機能(例: Pythonのround()、C#のMath.Round()、JavaのDecimalFormatなど)を使って、表示したい桁数に丸めてから表示します。

    # Pythonの例
    value_from_db = cursor.fetchone()[0] # 例として12.340000000000001
    display_value = round(value_from_db, 2) # 2桁に丸める
    print(display_value) # 12.34
    

浮動小数点数の計算誤差の蓄積

連続する計算や多数の浮動小数点数の合計などを行うと、小さな丸め誤差が蓄積され、最終的な結果が期待と大きく異なることがあります。

問題の例
0.1を10回足すと1.0になるはずが、0.9999999999999999のようになる。

トラブルシューティング/解決策

  • 誤差を許容するか、丸める
    最終的な結果を表示する際に、適切な桁数に丸めることで、見た目の誤差を解消します。
  • 計算の順序を検討する
    可能な場合、誤差を最小限に抑えるように計算の順序を工夫します(例: 同じような大きさの数を先に計算するなど)。ただし、これは複雑なケースであり、常に適用できるわけではありません。
  • 厳密な計算が必要な場合は整数型を使用する
    上記の通貨の例と同様に、金融計算や科学計算など、厳密な正確性が求められる場合は、最初から整数型で格納し、最小単位で計算を行うべきです。

REAL型とINTEGER型の混同

SQLiteの「データ型のアフィニティ」の特性により、REALカラムに整数を挿入したり、INTEGERカラムに浮動小数点数を挿入したりすることが可能です。これにより、意図しない型変換が行われることがあります。

問題の例
INTEGER型に宣言したカラムに12.34を挿入すると、小数点以下が切り捨てられて12として格納される。

トラブルシューティング/解決策

  • 挿入前にデータ型を確認する
    アプリケーション側で、データベースに挿入する値のデータ型が意図したものと一致しているか、または変換が必要な場合は適切に処理されているかを確認します。
  • カラムの型を適切に宣言する
    格納したいデータの種類に応じて、INTEGERまたはREALを適切に宣言します。

SQLiteの浮動小数点数(REAL型)を扱う際の最も重要なポイントは、浮動小数点数は近似値であるという根本的な理解です。この理解があれば、多くの「なぜ期待通りの値にならないのか?」という疑問に対する答えが見えてきます。



ここでは、sqlite3モジュールを使用して、SQLiteデータベースで浮動小数点数を操作する例を示します。

データベースの接続とテーブルの作成

まず、データベースに接続し、REAL型のカラムを持つテーブルを作成します。

import sqlite3

# データベースファイルに接続 (ファイルが存在しない場合は新規作成される)
conn = sqlite3.connect('products.db')
cursor = conn.cursor()

# テーブルを作成
# price カラムを REAL 型として定義
cursor.execute('''
    CREATE TABLE IF NOT EXISTS products (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        price REAL,
        weight REAL
    )
''')
conn.commit()
print("テーブル 'products' が作成されました。")

# 接続を閉じる
conn.close()

解説

  • price REAL, weight REAL: それぞれREAL型のカラムとして定義しています。これにより、小数点以下の値を持つ数値を格納できるようになります。
  • CREATE TABLE IF NOT EXISTS products (...): productsテーブルを作成します。
  • sqlite3.connect('products.db'): products.dbという名前のデータベースファイルに接続します。

浮動小数点数の挿入

REAL型のカラムに値を挿入します。Pythonのfloat型がSQLiteのREAL型にマップされます。

import sqlite3

conn = sqlite3.connect('products.db')
cursor = conn.cursor()

# データの挿入
products_to_insert = [
    ('Laptop', 1200.50, 2.5),
    ('Mouse', 25.99, 0.1),
    ('Keyboard', 75.00, 0.8),
    ('Monitor', 350.75, 4.2),
    ('Headphones', 99.99, 0.35)
]

cursor.executemany("INSERT INTO products (name, price, weight) VALUES (?, ?, ?)", products_to_insert)
conn.commit()
print(f"{len(products_to_insert)}件のデータが挿入されました。")

conn.close()

解説

  • executemany(): 複数のデータを効率的に挿入するために使用します。Pythonのタプルに含まれるfloat型の値が、SQLiteのREALカラムに適切に挿入されます。

浮動小数点数の取得と表示

REAL型の値を取得し、Pythonで表示します。

import sqlite3

conn = sqlite3.connect('products.db')
cursor = conn.cursor()

# 全ての製品データを取得
cursor.execute("SELECT id, name, price, weight FROM products")
rows = cursor.fetchall()

print("\n--- 全ての製品データ ---")
for row in rows:
    product_id, name, price, weight = row
    print(f"ID: {product_id}, 名前: {name}, 価格: {price}, 重さ: {weight} kg")
    # ここで price や weight は Python の float 型として取得されます

conn.close()

解説

  • 取得されたpriceweightは、Pythonのfloat型として扱われます。この段階では、データベースに格納されている精度そのままの値です。
  • cursor.fetchall(): クエリ結果をリストのリスト(またはタプルのリスト)として取得します。

浮動小数点数での条件検索(注意点を含む)

浮動小数点数での検索は、丸め誤差に注意が必要です。

import sqlite3

conn = sqlite3.connect('products.db')
cursor = conn.cursor()

print("\n--- 価格が100.00ドル以上の製品 ---")
cursor.execute("SELECT name, price FROM products WHERE price >= 100.00")
results = cursor.fetchall()
for row in results:
    print(f"名前: {row[0]}, 価格: {row[1]}")

print("\n--- 価格がちょうど25.99ドルの製品 (注意点あり) ---")
# 厳密な等値比較 - 動作するかもしれないが、丸め誤差によっては失敗する可能性あり
cursor.execute("SELECT name, price FROM products WHERE price = 25.99")
results = cursor.fetchall()
if results:
    for row in results:
        print(f"名前: {row[0]}, 価格: {row[1]} (厳密な比較)")
else:
    print("厳密な比較では見つかりませんでした。")

print("\n--- 価格が0.3の重さの製品 (丸め誤差による失敗例) ---")
# 0.3は2進数で正確に表現できないため、等値比較は失敗する可能性が高い
cursor.execute("SELECT name, weight FROM products WHERE weight = 0.3")
results = cursor.fetchall()
if results:
    for row in results:
        print(f"名前: {row[0]}, 重さ: {row[1]} (厳密な比較)")
else:
    print("厳密な比較では見つかりませんでした。(これはよくあることです)")

print("\n--- 許容誤差範囲での検索 (推奨される方法) ---")
# 0.3 ± 0.0000000001 の範囲で検索
epsilon = 0.0000000001
target_weight = 0.3
cursor.execute("SELECT name, weight FROM products WHERE weight BETWEEN ? - ? AND ? + ?",
               (target_weight, epsilon, target_weight, epsilon))
results = cursor.fetchall()
if results:
    for row in results:
        print(f"名前: {row[0]}, 重さ: {row[1]} (許容誤差範囲)")
else:
    print("許容誤差範囲でも見つかりませんでした。(データに問題がある可能性)")

conn.close()

解説

  • WHERE weight BETWEEN ? - ? AND ? + ?: これが浮動小数点数を比較する際の推奨される方法です。ターゲット値の周りに小さな許容範囲(epsilon)を設定し、その範囲内の値を検索します。
  • WHERE weight = 0.3: 0.3は2進数では正確に表現できないため、ほとんどの場合、この等値比較は失敗します。
  • WHERE price = 25.99: このような厳密な等値比較は、25.99がたまたま2進数で誤差なく表現できる場合や、非常に小さい誤差が許容される範囲に収まる場合にのみ成功します。
  • WHERE price >= 100.00: 範囲での比較は問題なく動作します。

浮動小数点数での計算

SQLクエリ内で直接、浮動小数点数に対して計算を行うことも可能です。

import sqlite3

conn = sqlite3.connect('products.db')
cursor = conn.cursor()

# 価格に消費税10%を上乗せした計算
print("\n--- 価格に10%の税金を加算した製品 ---")
cursor.execute("SELECT name, price, price * 1.10 AS price_with_tax FROM products")
results = cursor.fetchall()
for row in results:
    name, original_price, price_with_tax = row
    print(f"名前: {name}, 元の価格: {original_price:.2f}, 税込み価格: {price_with_tax:.2f}")

# 平均重さの計算
print("\n--- 製品の平均重さ ---")
cursor.execute("SELECT AVG(weight) FROM products")
average_weight = cursor.fetchone()[0]
print(f"平均重さ: {average_weight:.2f} kg")

# 特定の桁数に丸める (SQLのROUND関数を使用)
print("\n--- 価格を小数点以下2桁に丸めて表示 ---")
cursor.execute("SELECT name, ROUND(price, 2) FROM products")
results = cursor.fetchall()
for row in results:
    print(f"名前: {row[0]}, 丸めた価格: {row[1]}")

conn.close()

解説

  • :.2f: Pythonのf-string書式指定で、小数点以下2桁に丸めて表示しています。これはデータベースから取得したfloat値をPython側で整形する一般的な方法です。
  • ROUND(price, 2): SQLiteのROUND関数を使って、priceを小数点以下2桁に丸めて取得しています。これは表示上の丸めであり、データベースに格納されている元の値は変更されません。
  • AVG(weight): weightカラムの平均値を計算します。AVG関数は通常、REAL型の結果を返します。
  • price * 1.10 AS price_with_tax: SQL内で直接、価格に1.10を乗算しています。結果はREAL型として返されます。

整数型で通貨を扱う例(推奨される代替案)

丸め誤差を完全に回避するため、通貨などの厳密な計算が必要な場合に推奨される方法です。

import sqlite3

conn = sqlite3.connect('financial_data.db')
cursor = conn.cursor()

# テーブルを作成 (価格を「セント」単位でINTEGER型として格納)
cursor.execute('''
    CREATE TABLE IF NOT EXISTS transactions (
        id INTEGER PRIMARY KEY,
        description TEXT NOT NULL,
        amount_in_cents INTEGER, -- 例: $12.34 は 1234
        timestamp TEXT DEFAULT CURRENT_TIMESTAMP
    )
''')
conn.commit()
print("\nテーブル 'transactions' が作成されました。")

# データの挿入
# $10.50 を 1050 として格納
# $2.75 を 275 として格納
transactions_to_insert = [
    ('Groceries', 1050),
    ('Coffee', 275),
    ('Book', 2599),
]

for desc, amount in transactions_to_insert:
    cursor.execute("INSERT INTO transactions (description, amount_in_cents) VALUES (?, ?)", (desc, amount))
conn.commit()
print(f"{len(transactions_to_insert)}件のトランザクションデータが挿入されました。")

# データの取得と表示(セントからドルへの変換)
print("\n--- トランザクションデータ (セントからドルへ変換して表示) ---")
cursor.execute("SELECT description, amount_in_cents FROM transactions")
rows = cursor.fetchall()
for row in rows:
    description, amount_in_cents = row
    amount_in_dollars = amount_in_cents / 100.0 # float に変換して表示
    print(f"内容: {description}, 金額: ${amount_in_dollars:.2f}")

# 合計金額の計算(セント単位で計算し、最後にドルに変換)
print("\n--- 全てのトランザクションの合計金額 ---")
cursor.execute("SELECT SUM(amount_in_cents) FROM transactions")
total_cents = cursor.fetchone()[0]
total_dollars = total_cents / 100.0 if total_cents is not None else 0.0
print(f"合計金額: ${total_dollars:.2f}")

conn.close()
  • SUM(amount_in_cents): 合計も整数で計算されるため、丸め誤差の問題は発生しません。
  • amount_in_dollars = amount_in_cents / 100.0: 取得したセント単位の値を100で割ることで、ドル単位に変換して表示します。ここで100.0とすることで浮動小数点数での割り算になります。
  • amount_in_cents INTEGER: 金額を最小単位(セント)で整数として格納しています。


SQLiteは、他の多くのデータベースが持つDECIMALNUMERICといった固定小数点数型を直接サポートしていません。しかし、プログラマーはいくつかの代替手段を用いて、浮動小数点数の丸め誤差の問題に対処したり、より厳密な数値計算を実現したりすることができます。

整数型 (INTEGER) を使用して最小単位を格納する

これは、特に通貨や物理量の測定値など、厳密な計算と正確な表現が最も重要である場合に最も推奨される方法です。

  • ユースケース
    金融取引、会計、厳密な科学データ(ただし、非常に広い範囲をカバーする必要がない場合)。
  • デメリット
    • 変換の手間
      データベースへの挿入時と取得時に、アプリケーション側で値の変換(乗算/除算)を行う必要があります。
    • 最大値の制限
      INTEGER 型の最大値(通常9クアッドリオン以上)に収まる範囲である必要があります。非常に大きな数値や非常に高い精度が必要な場合、桁あふれに注意が必要です。
  • メリット
    • 計算の正確性
      整数演算は丸め誤差が発生しないため、合計、平均、比較などの計算が常に正確になります。
    • 厳密な等値比較
      = 演算子による比較が常に期待通りに機能します。

    • $12.341234 セントとして INTEGER 型で格納。
    • 3.14159 メートルを 314159 マイクロメートル(または3141590000ナノメートル)として INTEGER 型で格納。
  • 考え方
    浮動小数点数で表現される値を、その最小単位(例:円、セント、ミリグラム、マイクロメートルなど)に変換し、整数型で格納します。

Pythonでのコード例

import sqlite3

conn = sqlite3.connect('finance.db')
cursor = conn.cursor()

cursor.execute('''
    CREATE TABLE IF NOT EXISTS transactions (
        id INTEGER PRIMARY KEY,
        description TEXT NOT NULL,
        amount_in_cents INTEGER, -- 金額をセント単位で整数として格納
        transaction_date TEXT DEFAULT CURRENT_TIMESTAMP
    )
''')
conn.commit()

# データ挿入: $1.99 -> 199, $10.50 -> 1050
cursor.execute("INSERT INTO transactions (description, amount_in_cents) VALUES (?, ?)", ('Coffee', 199))
cursor.execute("INSERT INTO transactions (description, amount_in_cents) VALUES (?, ?)", ('Groceries', 1050))
conn.commit()

# データ取得と表示(セントからドルへ変換)
cursor.execute("SELECT description, amount_in_cents FROM transactions")
for row in cursor.fetchall():
    description, amount_in_cents = row
    amount_dollars = amount_in_cents / 100.0 # 表示時にfloatに変換
    print(f"Description: {description}, Amount: ${amount_dollars:.2f}")

# 合計金額の計算(整数で計算し、最後に変換)
cursor.execute("SELECT SUM(amount_in_cents) FROM transactions")
total_cents = cursor.fetchone()[0]
total_dollars = total_cents / 100.0 if total_cents is not None else 0.0
print(f"Total Amount: ${total_dollars:.2f}")

conn.close()

文字列型 (TEXT) を使用して数値を格納する

数値をTEXT型(文字列)として格納し、データベースから読み出した後にアプリケーション側で数値に変換する方法です。

  • ユースケース
    非常に高い精度が要求され、データベース内での計算が不要な場合、またはアプリケーションが特定の高精度ライブラリ(例: Pythonのdecimalモジュール)を使用する場合。
  • デメリット
    • 計算の複雑さ
      データベース内で直接、数値計算(SUM, AVGなど)を行うことができません。全ての計算をアプリケーション側で実装する必要があります。これはパフォーマンスに影響を与えたり、コードを複雑にしたりする可能性があります。
    • ソート順序の注意
      数値としてではなく、文字列としてソートされるため、例えば "10.0""2.0" より前にソートされてしまいます。
    • データ検証
      無効な数値文字列が挿入されるのを防ぐための検証ロジックをアプリケーション側で実装する必要があります。
  • メリット
    • 精度維持
      任意の精度で数値を格納できます(データベースのストレージ容量と文字列の長さの制限内)。
    • データベース側の制約なし
      SQLiteは文字列をそのまま格納するため、数値としての意味を解釈しようとしません。
  • 考え方
    数値を、その正確な文字列表現(例: "3.1415926535")としてデータベースに保存します。

Pythonでのコード例

import sqlite3
from decimal import Decimal, getcontext

# Decimalの精度を設定
getcontext().prec = 50 # 例として50桁の精度を設定

conn = sqlite3.connect('precise_data.db')
cursor = conn.cursor()

cursor.execute('''
    CREATE TABLE IF NOT EXISTS measurements (
        id INTEGER PRIMARY KEY,
        item TEXT NOT NULL,
        value_str TEXT -- 値を文字列として格納
    )
''')
conn.commit()

# データ挿入: Decimalオブジェクトを文字列に変換して格納
precise_value = Decimal('3.1415926535897932384626433832795028841971693993751')
cursor.execute("INSERT INTO measurements (item, value_str) VALUES (?, ?)", ('Pi', str(precise_value)))
cursor.execute("INSERT INTO measurements (item, value_str) VALUES (?, ?)", ('E', str(Decimal('2.71828182845904523536'))))
conn.commit()

# データ取得とDecimalオブジェクトへの変換
cursor.execute("SELECT item, value_str FROM measurements")
for row in cursor.fetchall():
    item, value_str = row
    # 文字列からDecimalオブジェクトに変換して計算や表示を行う
    converted_value = Decimal(value_str)
    print(f"Item: {item}, Value (Decimal): {converted_value}")
    # 例: 他のDecimal値との計算
    print(f"Value * 2: {converted_value * 2}")

conn.close()

外部の高精度数値ライブラリと連携する

アプリケーションのプログラミング言語が提供する、高精度な数値計算ライブラリを利用する方法です。

  • ユースケース
    金融計算、科学技術計算、厳密な比較が必要なあらゆる場面で、データベース内での直接計算の必要性が低い場合。
  • デメリット
    • パフォーマンス
      float型やdouble型に比べて計算が遅くなる傾向があります。
    • メモリ使用量
      より多くのメモリを使用する可能性があります。
    • データベースとの連携
      データベースのREAL型との間で相互変換が必要になります。TEXT型で格納する場合は、文字列変換の手間がかかります。
  • メリット
    • 正確な計算
      浮動小数点数とは異なる内部表現(通常は10進数ベース)を使用するため、丸め誤差が制御されます。
    • 制御可能な精度
      必要に応じて精度を設定できます。
  • C#の例
    System.Decimal型。
  • Javaの例
    java.math.BigDecimalクラス。
  • Pythonの例
    decimalモジュール(Decimal型)。
  • 考え方
    データベースにはREAL型またはTEXT型で数値を格納し、読み込んだ後にアプリケーション側で高精度ライブラリのオブジェクトに変換して計算を行います。保存する際は、高精度オブジェクトをREALまたはTEXTに変換して保存します。

上記「文字列型 (TEXT) を使用して数値を格納する」のコード例は、まさにこの方法(Pythonのdecimalモジュールと連携)を示しています。 REAL型で格納する場合でも、同様にデータベースから取得したfloat値をDecimal型に変換して計算し、保存時にfloatまたはstrに戻すことになります。

どの代替方法を選ぶべきか?

  • 限定的な精度要件で簡単な計算なら
    REAL型と、誤差を考慮した比較・丸め処理。
  • 最高の精度と計算制御が必要な場合
    外部の高精度数値ライブラリと連携し、TEXT型で格納。ただし、データベース内での計算はできません。
  • 最も推奨される(特に通貨など)
    整数型で最小単位を格納。計算の正確性とデータベース内での計算能力を両立できます。