DOBON.NET DOBON.NETプログラミング掲示板過去ログ

小数点付きの値を連結した時、指数表現の値が入ってしまう。

環境/言語:[開発環境 XP .NET2.0]
分類:[.NET]

お世話になります

小数点付きの値を取得して、それを元にクエリを発行させているのですが、
クエリの小数点付きの値が、なぜか指数表現されていて、クエリが動きません。


下のようにコーディングしています。

Dim wk As Single
Dim strColumn As String
〜〜〜〜〜〜〜〜〜〜〜〜〜

wk = "小数点付きの値"

strColumn = "INSERT INTO TABLE01(項目1,項目2,項目3)
strColumn = strColumn & " VALUES('" & DR1(0) & "','" & wk & "','" & DR1(1) & "')"


WKはクエリ直前までは、小数点ありなんですが、クエリ文を見ると指数表示になっています。
型変換がされているような感じはするんですが、どうすれば小数が取れるのかわかりません。

どなたかご教授ねがえませんでしょうか?

> strColumn = strColumn & " VALUES('" & DR1(0) & "','" & wk & "','" & DR1(1) & "')"

wk.ToString を使った方がよくありませんか?
ちなみにクエリ文に関しては、以下推奨です。

ADO.NET における SQL インジェクション対策ttp://blogs.yahoo.co.jp/hilapon/2397897.html
■No25068に返信(ひらぽんさんの記事)
> wk.ToString を使った方がよくありませんか?
というかSQL文の編集はVB上ではただの文字列編集なのだから

Dim wk As String

でいいのでは?表現できないの数値だった時の誤差もあるんだし。

> どうすれば小数が取れるのかわかりません。
元の"小数点付きの値"の小数部も取ろうとしてるのですか?
指数表示にしないだけで、"小数点付きの値"の小数部は
残したいのですか?

…どっちにしろ文字列のまま加工すれば良いと思いますが。
>>wk.ToString を使った方がよくありませんか?
> というかSQL文の編集はVB上ではただの文字列編集なのだから
>
> Dim wk As String
>
> でいいのでは?表現できないの数値だった時の誤差もあるんだし。

意味不明。数値をクエリに渡すんでしょ?
あと仮にフォーマットをかけるんなら、以下でいいです。

Single.ToString (String)

もっともクエリに直接変数を結合するのは危険なんですがね。┐(´д`)┌ヤレヤレ
少なくともうちの現場では許されません。

ADO.NET における SQL インジェクション対策
http://blogs.yahoo.co.jp/hilapon/2397897.html
2009/07/30(Thu) 11:35:37 編集(投稿者)

■No25074に返信(ひらぽんさんの記事)
> ADO.NET における SQL インジェクション対策
提示されたサンプルコードでそれは必ずしも成り立ちません。

直前に文字列としてハードコーディングできるサンプルとなっています。
その内容が"小数点付きの値"と限定されるなら SQL インジェクション対策は
必要ないのでは?

もちろん、今後のあらゆる仕様変更に対応するなら適用したほうが良いのでしょうが、
取得先が画面上のテキストボックスとかで無く、内部処理のみで利用される限定された
データなら、その対応工数が無駄な工数だと判断されることもあります。
また、SQL インジェクション対策はパラメータ化する手法だけではありません。
"小数点付きの値"を取得する段階で入力チェックにより防ぐことも可能です。

つまり、予備知識としては重要ですが、質問の内容と直接関係ありません。

> 数値をクエリに渡すんでしょ?
"小数点付きの値"で数値になっているでしょう?
わざわざ数値型に型変換して再度文字列型に型変換する意味がありません。
数値として有効かどうか調べるなら、全くプログラムとして足りていませんし、
> Single.ToString (String)
でも解決しませんし、引数の String まで具体的に教えてあげないと
> strColumn = strColumn & " VALUES('" & DR1(0) & "','" & wk & "','" & DR1(1) & "')"
と同じ結果に成り得ますよね?

[追記]
読み直して
> 表現できないの数値だった時の誤差
この説明では確かに意味が分からないかも?と思いました。
丸め誤差の話です。Single に入れる時点で全ての数値を正確に表現できません。
誤差が生じます。もちろん、データベースに入れた時点でも起こりそうですが、
そういった情報が提示されていないため、VB側で下手な加工をすべきでは無い
と言いたかったのです。
ひらぽんさん、るしぇさん回答ありがとうございます。

ひらぽんさん、るしぇさんの仰るコーディングを試してみたのですが、
小数が正しくでるパターン、でないパターンがあることがわかりました。

小数が”0.0138”は表示されているのですが、”0.0000875656742〜(続)”
のパターンが指数表現になります。
小数以下が数値の桁数が多いと指数表現になるのでしょうか?
> "小数点付きの値"で数値になっているでしょう?
> わざわざ数値型に型変換して再度文字列型に型変換する意味がありません。

はぁ?私は

> Dim wk As String

これの意味が意味不明だったの発言したまでですよ?

> Dim wk As Single
> wk = "小数点付きの値"

質問者は明らかに Single として宣言してますよね。
> 小数が”0.0138”は表示されているのですが、”0.0000875656742〜(続)”
のパターンが指数表現になります。
> 小数以下が数値の桁数が多いと指数表現になるのでしょうか?

こちらが詳しいです。
http://homepage1.nifty.com/MADIA/vb/vb_bbs/200403/200403_04030041.html
2009/07/30(Thu) 16:07:58 編集(投稿者)

■No25077に返信(HIPONさんの記事)
> 小数が正しくでるパターン、でないパターンがあることがわかりました。
値によっては指数表現どころか、"-∞" や "NaN (非数値)" といった表現となる事もありますよ。

Dim z As Single = -1.0 / 0.0
MsgBox(z)


> ”0.0000875656742〜(続)”のパターンが指数表現になります。
これは Single や Double が、数値を二進数の指数表現によって管理している事によるものです。


> 小数以下が数値の桁数が多いと指数表現になるのでしょうか?
数値を文字列にする際に、特定の書式で表現したいのであれば、
.ToString(書式文字列) メソッドや String.Format メソッドを用いて変換しましょう。


また、小数以下の桁数が重要な意味を持つ場合には、データを Single で管理するのではなく、
Decimal にすることを検討してください。こちらを使えば、指数表現になることもありませんし、
小数点以下の桁数も保持されます。(ただしこの場合、変換時の誤差を防ぐためにも、
Single な値を Decimal に変換するのはではなく、終始一貫して Decimal を使う必要があります)


Dim a As Decimal = CDec("1.01")
Dim b As Decimal = CDec("1.010")
Dim c As Decimal = CDec("1.0100")
Dim d As Decimal = CDec("1.01000")

Debug.WriteLine("値としては同一なので、どれも True を返す")
Debug.WriteLine(a = b) 'True
Debug.WriteLine(a = c) 'True
Debug.WriteLine(a = d) 'True
Debug.WriteLine(b = c) 'True
Debug.WriteLine(b = d) 'True
Debug.WriteLine(c = d) 'True

Debug.WriteLine("文字列として出力すると、それぞれ桁数が保持されている")
Debug.WriteLine(a) '1.01
Debug.WriteLine(b) '1.010
Debug.WriteLine(c) '1.0100
Debug.WriteLine(d) '1.01000

Debug.WriteLine("書式指定すれば、同じ桁数表現にする事も可能")
Debug.WriteLine(a.ToString("0.000000")) '1.010000
Debug.WriteLine(b.ToString("0.000000")) '1.010000
Debug.WriteLine(c.ToString("0.000000")) '1.010000
Debug.WriteLine(d.ToString("0.000000")) '1.010000
■No25080に返信(ひらぽんさんの記事)
>> wk = "小数点付きの値"
>
>質問者は明らかに Single として宣言してますよね。
質問者さんもSQLの編集で使ってますが、VBのコード上でダブルクォーテーションで
挟む場合、文字列データとなります。
つまり、ボクは有効桁数も丸め誤差も考慮に入れてない文字列型として用意された
数値データを Single に入れてしまっていると解釈しました。

ひらぽんさんはその行為自体も質問者さんの意図だと解釈した。
もしくは、文字列データではなく、数値型の数値データから話を始めてよいと
解釈したわけですね。理解しました。
> つまり、ボクは有効桁数も丸め誤差も考慮に入れてない文字列型として用意された
> 数値データを Single に入れてしまっていると解釈しました。

理解して頂きありがとうございます。<(_ _)>
なるほど・・・たしかに読み方によってはそう読めなくもないですね。(^^;

あとクエリパラメータの件に関して反論はあるのですが、
本題と思いっきりずれてしまうので、またの機会にさせて頂きます。<(_ _)>
ひらぽんさん、るしぇさん回答ありがとうございます。

結局下記のようにフォーマット指定を行えば指数表示しなくなりました。
strColumn = strColumn & " VALUES('" & DR1(0) & "','" & wk.ToString("0.000000") & "','" & DR1(1) & "')"

ひらぽんさん、るしぇさん ありがとうございました。
解決済み!
この掲示板では、質問者であっても、回答者であっても、言葉遣いなどの礼儀を守っていただくルールになっています。

ひらぽんさんの No25074 や No25080 などの投稿を拝見させていただくと、このルールをご存じないように見受けられます。もしまだ「書き込みのルールについて」をお読みでなければ、一度目をお通しください。面倒だとは思いますが、ご協力をお願いいたします。

書き込みのルールについて
http://dobon.net/vb/bbs/index.html
解決済み!
> 書き込みのルールについて
> http://dobon.net/vb/bbs/index.html

了解いたしました。上記ルールを遵守するようにいたします。<(_ _)>

DOBON.NET | プログラミング道 | プログラミング掲示板