質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Q&A

解決済

1回答

382閲覧

Python3 PostgreSQL real型で数字をそのまま保存、抽出できるようにしたい

person

総合スコア223

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

0グッド

1クリップ

投稿2023/03/08 01:00

編集2023/03/08 01:49

PythonからPostgreSQLに整数、小数を保存します。
列はreal型です。

入力値がそのまま保存されればよいのですが、数字が変わることがあります。
入力値によってはそのまま保存されるものもあります。

入力PostgreSQL real型での保存値結果
999999999999同じ
0.9999990.999999同じ
9999.999910000変わる
10000001e+06変わる

入力した数字がこのまま保存されるか、変わってしまうかをPythonで判別することは可能でしょうか。

Tkinter(GUIアプリ)でPostgreSQLに保存した数字を使いたいので、変わってほしくないです。

使うのは正整数、正小数のみです。
桁数は整数3桁、小数4桁ぐらいが全体的な目安です。
しかし、GUIの入力項目によって入力の目安範囲は変わりますので、許容される範囲が多いに越したことはないです。
(999.9999以下のみOKとしてもいいのですが、例えばreal型は整数9999でもそのまま保存されるのでそういうのは許容できた方がうれしいです。)

環境
Windows10

C:\Users\USER>psql --version psql (PostgreSQL) 14.1 C:\Users\USER>python --version Python 3.8.2

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bsdfan

2023/03/08 13:44

正確さを求めるなら、DECIMAL型を使うべきケースだと思うのですが、REALでやりたいということですか?
guest

回答1

0

ベストアンサー

入力した数字がこのまま保存されるか、変わってしまうかをPythonで判別することは可能でしょうか。

まず、PostgreSQLでのreal型は(通常は)単精度の浮動小数点値のようですが、python自体には単精度の型は存在しません。
つまり、いったんPythonのtkinter上に表示~なんらか入力された値は倍精度であるため、原理的にこのまま保存することはできません。
また見た目上同じな「0.999999」であっても、単精度と倍精度では異なる値となります。

どのようなルールで判別したいのか分かりませんが
numpy.float32が使えるので、numpyの数値に変換して元の値と==で、あるいはmath.iscloseで
あるいは文字列化した結果が同じか?なりで判定すればよいかと思います。

Python

1import numpy as np 2import math 3 4a1 = np.array([999999, 0.999999, 9999.9999, 1000000], dtype=float) 5a2 = a1.astype(np.float32) 6 7for x, y in zip(a1, a2): 8 print(x, y, x==y, math.isclose(x,y), str(x)==str(y), x-y) 9""" 10999999.0 999999.0 True True True 0.0 110.999999 0.999999 False False True 1.327896115288496e-08 129999.9999 10000.0 False False False -9.999999929277692e-05 131000000.0 1000000.0 True True True 0.0 14"""

投稿2023/03/08 01:47

編集2023/03/08 04:51
can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

person

2023/03/08 04:01

回答ありがとうございます。 質問にある表とコードの結果に差があります。 ご提示のコードの結果は上から True, False, False, True となっていますが、質問文にある表でいくと True, True, False, False となってほしいです。
can110

2023/03/08 04:05

- 質問に提示されている表がどのような手順、手段で作成されたものか - どのようなルール(仕様)で理想とする結果True, True, False, Falseになるのか が分からないので、なんともいえません。 「1e+06」って「1000000」と同じに思えますが。
person

2023/03/08 04:36 編集

> 質問に提示されている表がどのような手順、手段で作成されたものか PostgreSQLのreal型列に手打ちで小数適当に入れて更新したさいに、pgAdminで表示された結果を書きました。 > 「1e+06」って「1000000」と同じに思えますが。 これは私の理解不足でした。申し訳ないです。 1e+06を変数に入れて、再度変数参照したときに1000000という値が返ってきているようなので、Trueでいいです。 0.999999については、Trueであってほしいです。
can110

2023/03/08 04:52

> 0.999999については、Trueであってほしいです。 なぜそうなるのか?を明記すれば適切な回答が得られやすくなるかと思います。 (たんに文字列化して一致するかどうかでよい?)
person

2023/03/08 08:04

この入力した小数は、金額の計算に使います。 そのため、文字列化しても再びfloat()でキャストして入力時と異なる数に戻ってしまっては困ります。
can110

2023/03/08 08:16 編集

回答ではあくまで質問に記載されている質問内容である「判定」についての方法を提示しています。 そのあとの金額の計算をどこでどのようにするのか? つまり結局のところ「何をどうしたいのか」が分からないので回答に困りますが とりあえず「再びfloat()でキャストして~」といったことをしなければよいのではないでしょうか。 (numpyで単精度のまま計算するなど)
person

2023/03/10 01:13

そうですね。 floatに戻してたのでdecimal前提で進めます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問