-
数値の小数点以下の丸め処理を行うには Math オブジェクトを使います。 Math オブジェクトは数学的な定数と関数を提供する組み込みのプロパティとメソッドを持っています。
今回の丸め処理には、以下の様に切り捨て 四捨五入 切り上げ を行うメソッドがあります。- Math.floor() メソッド : 引数として与えた数以下の最大の整数を返します。
- Math.round() メソッド : 引数として与えた数を四捨五入して、もっとも近似の整数を返します。
- Math.ceil() メソッド : 引数として与えた数以上の最小の整数を返します。
今回は、これらのメソッドを使って丸め処理の関数を作成してみました。
丸め処理の関数
/* * 丸め処理 * P_dblVal : 対象値 * P_intRound : 小数点以下丸め処理(1:切り捨て, 2:四捨五入, 3:切り上げ) * return : 丸めた値 */ function calcRound(P_dblVal, P_intRound) { var dblRet; // 丸め処理 switch (parseInt(P_intRound)) { case 1: dblRet = Math.floor(P_dblVal); break; case 2: dblRet = Math.round(P_dblVal); break; case 3: dblRet = Math.ceil(P_dblVal); break; default: dblRet = Math.round(P_dblVal); break; } // 戻り値 return dblRet; }
上記の関数を実行させてみます。console.log('切り捨て:(10.4) = ' + calcRound(10.4, 1)); console.log('四捨五入:(10.4) = ' + calcRound(10.4, 2)); console.log('切り上げ:(10.4) = ' + calcRound(10.4, 3)); console.log('切り捨て:(10.5) = ' + calcRound(10.5, 1)); console.log('四捨五入:(10.5) = ' + calcRound(10.5, 2)); console.log('切り上げ:(10.5) = ' + calcRound(10.5, 3)); console.log('切り捨て:(-10.5) = ' + calcRound(-10.5, 1)); console.log('四捨五入:(-10.5) = ' + calcRound(-10.5, 2)); console.log('切り上げ:(-10.5) = ' + calcRound(-10.5, 3));実行結果がコンソールには以下の結果が表示されます。
切り捨て:(10.4) = 10 四捨五入:(10.4) = 10 切り上げ:(10.4) = 11 切り捨て:(10.5) = 10 四捨五入:(10.5) = 11 切り上げ:(10.5) = 11 切り捨て:(-10.5) = -11 四捨五入:(-10.5) = -10 切り上げ:(-10.5) = -10
小数点以下1位の丸めは出来たのですが、小数点以下2位や3位での丸めはどうすればいいのでしょうか。 方法としては、小数点以下2位での丸めは数値を一旦10倍してから、丸め処理を行いその結果を10で割れば出来るようです。var valTest = 10.15; console.log('切り捨て:(10.15) = ' + Math.floor(valTest * 10) / 10); console.log('四捨五入:(10.15) = ' + Math.round(valTest * 10) / 10); console.log('切り上げ:(10.15) = ' + Math.ceil(valTest * 10) / 10);実行結果がコンソールには以下の結果が表示されます。
切り捨て:(10.15) = 10.1 四捨五入:(10.15) = 10.2 切り上げ:(10.15) = 10.2
これを参考に上記の関数を変更してみます。
丸め処理の関数2(小数点以下桁数の引数追加)
/* * 丸め処理・小数点以下の桁数指定 * P_dblVal : 対象値 * P_intRound : 小数点以下丸め処理(1:切り捨て, 2:四捨五入, 3:切り上げ) * P_intDpUnit: 小数点以下桁数 * return : 丸めた値 */ function calcRoundDp(P_dblVal, P_intRound, P_intDpUnit) { var dblRet; var dblPow = Math.pow(10, P_intDpUnit); P_dblVal = P_dblVal * dblPow; // 丸め処理 switch (parseInt(P_intRound)) { case 1: dblRet = Math.floor(P_dblVal); break; case 2: dblRet = Math.round(P_dblVal); break; case 3: dblRet = Math.ceil(P_dblVal); break; default: dblRet = Math.round(P_dblVal); break; } // 戻り値 return dblRet / dblPow; }
上記の関数を実行させてみます。var valTest = 10.15; console.log('小数点以下2位を丸め処理'); console.log('切り捨て:(10.15) = ' + calcRoundDp(valTest, 1, 1)); console.log('四捨五入:(10.15) = ' + calcRoundDp(valTest, 2, 1)); console.log('切り上げ:(10.15) = ' + calcRoundDp(valTest, 3, 1)); console.log('小数点以下1位を丸め処理'); console.log('切り捨て:(10.15) = ' + calcRoundDp(valTest, 1, 0)); console.log('四捨五入:(10.15) = ' + calcRoundDp(valTest, 2, 0)); console.log('切り上げ:(10.15) = ' + calcRoundDp(valTest, 3, 0)); console.log('1の位を丸め処理'); console.log('切り捨て:(10.15) = ' + calcRoundDp(valTest, 1, -1)); console.log('四捨五入:(10.15) = ' + calcRoundDp(valTest, 2, -1)); console.log('切り上げ:(10.15) = ' + calcRoundDp(valTest, 3, -1)); console.log('10の位を丸め処理'); console.log('切り捨て:(10.15) = ' + calcRoundDp(valTest, 1, -2)); console.log('四捨五入:(10.15) = ' + calcRoundDp(valTest, 2, -2)); console.log('切り上げ:(10.15) = ' + calcRoundDp(valTest, 3, -2));実行結果がコンソールには以下の結果が表示されます。
小数点以下2位を丸め処理 切り捨て:(10.15) = 10.1 四捨五入:(10.15) = 10.2 切り上げ:(10.15) = 10.2 小数点以下1位を丸め処理 切り捨て:(10.15) = 10 四捨五入:(10.15) = 10 切り上げ:(10.15) = 11 1の位を丸め処理 切り捨て:(10.15) = 10 四捨五入:(10.15) = 10 切り上げ:(10.15) = 20 10の位を丸め処理 切り捨て:(10.15) = 0 四捨五入:(10.15) = 0 切り上げ:(10.15) = 100
結果から見て、上手く動作している様です。
小数点以下の桁数に大きな値を与えると、関数内の Math.pow で桁あふれが発生する様です。 そのため、桁数指定は10桁以内ぐらいが妥当かと思います。(もっともそこまでの桁数で計算する処理も無いとは思いますが...)
PR -
EXEファイルの実行フォルダが必要になることはよくあります。 フォルダを取得して、そこからの相対フォルダ参照で、データフォルダなどを作成・参照を行ったりしますので、 その方法について示します。
まず最初は通常のWindowsフォームを持っているEXEファイルに付いてです。WindowsフォームでのEXEファイル取得
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim strPath As String = "" 'System.Windows.Forms.Application のSharedプロパティ「ExecutablePath」を参照 ' アプリケーションを開始した実行可能ファイルのパスを、ファイル名を含めて取得します。 strPath = System.Windows.Forms.Application.ExecutablePath Console.WriteLine("ExecutablePathdでのExeフルパス:[{0}]", strPath) '因みに、System.Windows.Forms.Application のSharedプロパティ「StartupPath」を参照 ' アプリケーションを開始した実行可能ファイルのファイル名を含まないパス取得します。 strPath = System.Windows.Forms.Application.StartupPath Console.WriteLine("StartupPathでのExeフルパス:[{0}]", strPath) End Sub実行結果は以下の様になります。
ExecutablePathdでのExeフルパス:[C:¥TestSrv¥BlogTest¥BlogTest¥bin¥Debug¥BlogTest.EXE] StartupPathでのExeフルパス:[C:¥TestSrv¥BlogTest¥BlogTest¥bin¥Debug]
コンソールアプリの場合にはこれは使えないので、以下の様に自分自身のアセンブリを取得し、そのLocationプロパティ を取得することでEXEのフルパスが取得できます。
GetExecutingAssembly().Location でのEXEファイル取得
Module MdlMainPath 'Main関数 Sub Main() Dim strPath As String = "" 'GetExecutingAssembly().Locationでの実行ファイルのパスを取得する strPath = System.Reflection.Assembly.GetExecutingAssembly().Location Console.WriteLine("GetExecutingAssembly().LocationでのExeフルパス:[{0}]", strPath) 'パスから実行フォルダのみを取り出す strPath = System.IO.Path.GetDirectoryName(strPath) Console.WriteLine("GetExecutingAssembly().LocationでのExeフォルダ:[{0}]", strPath) End Sub End Module実行結果は以下の様になります。
GetExecutingAssembly().LocationでのExeフルパス:[C:¥TestSrv¥BlogTest¥BlogTest¥bin¥Debug¥BlogTest.exe] GetExecutingAssembly().LocationでのExeフォルダ:[C:¥TestSrv¥BlogTest¥BlogTest¥bin¥Debug]
関連する記事
⇒フォルダコピー(サブフォルダ以下も含む):[Directory.GetFiles,Directory.GetDirectories]
⇒指定フォルダ内の全ファイルを削除 :[Directory.GetFiles,File.Delete]
⇒指定フォルダ内の全ファイルをクリア :[Directory.GetFiles,File.Delete]
-
あるデータ処理において文字列を Shift-JIS と考えて切出す必要があり、 文字列を Shift-JIS と見立てて切出す関数を作ってみましたので紹介します。
VB.NET において通常、文字列は Unicode(UTF-8) で処理されています。 ほとんどの場合は文字コードのことを特に考えなくても問題は無いのですが、まれにシリアル通信等で外部とのやり取りを行う場合に 文字列のコードが Shift-JIS を使っていたりします。こういった場合に今回の関数群は使えると思います。
では、最初に文字列の中から文字列のバイト位置(Shift-JISと考えて)と切出すバイト数を指定し、処理する関数である MidB(以前の VB では Mid$ とされていたもの)を記します。
開始位置、切出しバイト数の指定値により、全角文字の泣き別れが発生しますので、関数の処理手順は以下の様に行います。- 開始位置が「1」未満の場合は空文字を返す。
- 文字列をShift-JISエンコードでバイト配列に分解し、開始位置が配列の長さより大きい場合は空文字を返す。
- 先頭から見て指定位置の直前までを切出し最後の文字が漢字の左半分の場合、開始位置と切出しバイト数を調整。
- 調整された開始位置とバイト数で文字列を切出し最後の文字が漢字の左半分の場合、切出しバイト数を調整。
- 調整された開始位置とバイト数で文字列を生成する。
MidB 関数
'''
''' 開始位置、バイト指定による文字列切出・Mid関数 ''' ''' <param name="astrSrc">対象文字列</param> ''' <param name="aintStart">開始位置(先頭1から)</param> ''' <param name="aintLen">切出しバイト数</param> '''切出し文字列 Private Function MidB(ByVal astrSrc As String, ByVal aintStart As Integer, ByVal aintLen As Integer) As String Try '開始を「0」からの指標 Dim intStart As Integer = aintStart - 1 '開始が1より小さい場合は空文字を返す If intStart < 0 Then Return "" End If 'Shift-JISでエンコーディングしてバイト配列に分解 Dim objEnc As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS") Dim arrBytes As Byte() = objEnc.GetBytes(astrSrc) '開始がバイト配列より大きい場合は空文字を返す If intStart > arrBytes.Length - 1 Then Return "" End If '取り出しバイト数 Dim intLen As Integer = aintLen If (intStart + aintLen) > (arrBytes.Length - 1) Then intLen = arrBytes.Length - intStart End If '先頭から見て指定位置の直前までを切り出す Dim strTemp As String = objEnc.GetString(arrBytes, 0, intStart) If strTemp.EndsWith(ControlChars.NullChar) Or strTemp.EndsWith("・") Then '最後の文字が漢字の左半分の場合、切出の先頭は泣き別れになる intStart += 1 '開始位置を右へ intLen -= 1 '切出バイト数を1個少なくする End If '修正位置とバイト数で切り出す strTemp = objEnc.GetString(arrBytes, intStart, intLen) If strTemp.EndsWith(ControlChars.NullChar) Or strTemp.EndsWith("・") Then '最後の文字が漢字の左半分の場合、泣き別れになる intLen -= 1 '切出バイト数をさらに1個少なくする End If '文字列を返す Return objEnc.GetString(arrBytes, intStart, intLen) Catch ex As Exception Return "" End Try End Function以前の VB の Mid$ では第3引数が無く、開始位置から右側を全て返す関数がありましたので、 同じ関数名で引数の数が異なる関数を以下に記します。
MidB 関数(開始位置以降の切出し)
'''
''' 開始位置以降の文字列切出・Mid関数 ''' ''' <param name="astrSrc">対象文字列</param> ''' <param name="aintStart">開始位置(先頭1から)</param> '''切出し文字列 Private Function MidB(ByVal astrSrc As String, ByVal aintStart As Integer) As String Try '開始を「0」からの指標 Dim intStart As Integer = aintStart - 1 '開始が1より小さい場合は空文字を返す If intStart < 0 Then Return "" End If 'Shift-JISでエンコーディングしてバイト配列に分解 Dim objEnc As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS") Dim arrBytes As Byte() = objEnc.GetBytes(astrSrc) '開始がバイト配列より大きい場合は空文字を返す If intStart > arrBytes.Length - 1 Then Return "" End If '実際の処理は上記の関数をコール Return MidB(astrSrc, aintStart, arrBytes.Length - aintStart + 1) Catch ex As Exception Return "" End Try End Functionさらに、文字列の左側から指定バイト数を切り出す LeftB 関数、文字列の右側から指定バイト数を切り出す RightB 関数を記します。 この2個の関数は最初の MidB 関数を利用しています。
LeftB 関数 , RightB 関数
'''
''' バイト数指定による文字列の左側切出し・Left関数 ''' ''' <param name="astrSrc">対象文字列</param> ''' <param name="aintLen">左側切出しバイト数</param> '''切出し文字列 Private Function LeftB(ByVal astrSrc As String, ByVal aintLen As Integer) As String '先頭から指定バイト数を切り出す Return MidB(astrSrc, 1, aintLen) End Function '''''' バイト数指定による文字列の右側切出し・Right関数 ''' ''' <param name="astrSrc">対象文字列</param> ''' <param name="aintLen">右側切出しバイト数</param> '''切出し文字列 Private Function RightB(ByVal astrSrc As String, ByVal aintLen As Integer) As String 'Shift-JISでエンコーディングしてバイト配列に分解 Dim objEnc As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS") Dim arrBytes As Byte() = objEnc.GetBytes(astrSrc) 'バイト数がバイト配列の個数より多い場合は、対象文字列そのまま返す If aintLen >= arrBytes.Length Then Return astrSrc End If '開始位置 Dim intStart As Integer = arrBytes.Length - aintLen + 1 '先頭から指定バイト数を切り出す Return MidB(astrSrc, intStart, aintLen) End Functionこれらの関数を実行する例を以下に記します。 これはフォームにボタンを設置し、クリックイベント時に、各関数の処理を行い結果をデバッグ用の出力ウインドウに表示しています。
Private Sub btnStringCut_Click(sender As Object, e As EventArgs) Handles btnStringCut.Click '表示 Dim strSrc As String = "あいうえお" Dim i As Integer '引数が3個ある MidB 関数 Dim nCut As Integer = 6 For i = 0 To 10 Dim strDes As String = MidB(strSrc, i, nCut) Console.WriteLine("MidB(""{0}"", {1}, {2}) : /{3}/", strSrc, i, nCut, strDes) Next '引数が2個の MidB 関数 For i = 0 To 10 Dim strDes As String = MidB(strSrc, i) Console.WriteLine("MidB(""{0}"", {1}) : /{2}/", strSrc, i, strDes) Next 'LeftB 関数 For i = 0 To 10 Dim strDes As String = LeftB(strSrc, i) Console.WriteLine("LeftB(""{0}"", {1}) : /{2}/", strSrc, i, strDes) Next 'RightB 関数 For i = 1 To 11 Dim strDes As String = RightB(strSrc, i) Console.WriteLine("RightB(""{0}"", {1}) : /{2}/", strSrc, i, strDes) Next End Sub結果の表示は以下の通りです。
MidB("あいうえお", 0, 6) : // MidB("あいうえお", 1, 6) : /あいう/ MidB("あいうえお", 2, 6) : /いう/ MidB("あいうえお", 3, 6) : /いうえ/ MidB("あいうえお", 4, 6) : /うえ/ MidB("あいうえお", 5, 6) : /うえお/ MidB("あいうえお", 6, 6) : /えお/ MidB("あいうえお", 7, 6) : /えお/ MidB("あいうえお", 8, 6) : /お/ MidB("あいうえお", 9, 6) : /お/ MidB("あいうえお", 10, 6) : // MidB("あいうえお", 0) : // MidB("あいうえお", 1) : /あいうえお/ MidB("あいうえお", 2) : /いうえお/ MidB("あいうえお", 3) : /いうえお/ MidB("あいうえお", 4) : /うえお/ MidB("あいうえお", 5) : /うえお/ MidB("あいうえお", 6) : /えお/ MidB("あいうえお", 7) : /えお/ MidB("あいうえお", 8) : /お/ MidB("あいうえお", 9) : /お/ MidB("あいうえお", 10) : // LeftB("あいうえお", 0) : // LeftB("あいうえお", 1) : // LeftB("あいうえお", 2) : /あ/ LeftB("あいうえお", 3) : /あ/ LeftB("あいうえお", 4) : /あい/ LeftB("あいうえお", 5) : /あい/ LeftB("あいうえお", 6) : /あいう/ LeftB("あいうえお", 7) : /あいう/ LeftB("あいうえお", 8) : /あいうえ/ LeftB("あいうえお", 9) : /あいうえ/ LeftB("あいうえお", 10) : /あいうえお/ RightB("あいうえお", 1) : // RightB("あいうえお", 2) : /お/ RightB("あいうえお", 3) : /お/ RightB("あいうえお", 4) : /えお/ RightB("あいうえお", 5) : /えお/ RightB("あいうえお", 6) : /うえお/ RightB("あいうえお", 7) : /うえお/ RightB("あいうえお", 8) : /いうえお/ RightB("あいうえお", 9) : /いうえお/ RightB("あいうえお", 10) : /あいうえお/ RightB("あいうえお", 11) : /あいうえお/関連する記事
⇒文字列の連結をStringBuilderで高速に行う(StringBuilder)
⇒SerialPortコントロールの使い方その3(外部装置からの垂れ流しデータ受信)
-
VB.NETでプログラムを組むシステムでは、データ処理のものも多いものです。 データ処理と言えば、当然のことながらデータベースを使うことがあります。 現在では SQL を使ったデータベースがほとんどで、今まで利用したものとしては 「Oracle」「MySQL」「MS-SQL」「PostgleSQL」があります。
それぞれは標準の SQL に準拠しているため、文法的にはほぼ同じですが、 関数などに少し違いがあります。
何れかのデータベースの SQL を学べば上記のものはすぐに慣れるものです。 以下のサイトは私が作ったものですが Oracle SQL 入門 サイトです。 SQL に興味のある方はご覧になってください。OracleSQL入門
-
SELECT文に関する基礎的なこと
-
さらにSELECT文に関する基礎的なことのその2
-
副問い合わせを含むSELECT文について
-
集合演算子を使ったSELECT文について
-
CASE式を使ったSELECT文について
-
WHERE句にEXISTS演算子を使ったSELECT文について
-
クロス結合、等結合、外部結合、自己結合
-
等結合(INNER JOIN)、外部結合(LEFT JOIN)
-
CREATE TABLE 文、ALTER TABLE 文
-
算術演算子、文字結合演算子
-
INSERT・・・VALUES文、INSERT・・・SELECT文について
-
UPDATE文について
-
DELETE文について
-
OracleSQLの関数の中でよく使用するもの
-
CREATE SEQUENCE文等について
-
ビューについて
-
索引について
-
トランザクション・ロックについて
-
Oracle PL/SQL入門
-
Oracle FUNCTIONの作成
-
Oracle TABLE FUNCTIONの作成
-
その他・Tips等について
本書用のWebアプリを使ってSQLを実行し学習していきます。初心者の方に分かりやすく、図表を多く使って解説されています。 学習の最後には200問越えのドリルが付いていてSQLのスキルが試せる様になっています。
-
-
文字列の分解は、文字列オブジェクトのメソッド Split を用いて行います。 一般的な例として日付を分解する方法を見てみます。
'文字列の分解の例(年月日を例とする) Dim strTest As String = "2019/08/01" '"/"(スラッシュ)で分解する Dim arr As String() = strTest.Split("/") '3個の配列で「arr」には入る For i As Integer = 0 To UBound(arr) Console.WriteLine("arr({0}) : {1}", i, arr(i)) Next動作結果として、デバッグ時の出力ウインドウには以下の様に表示されます。 日付文字列が「/」(スラッシュ)で分解されることが分かります。 但し、注意する点は、配列要素には指標が「0」から順に格納されることです。
上の例では、文字列配列「arr」が何個返されるか分からないので、 UBound 関数を使って最後の指標の値を指定しています。arr(0) : 2019 arr(1) : 08 arr(2) : 01
さらに、以下の例を見て下さい。
'文字列の分解の例(年月日を例とする:スラッシュは無い) strTest = "20190801" '"/"(スラッシュ)で分解する arr = strTest.Split("/") '1個の配列で「arr」には入るはず For i As Integer = 0 To UBound(arr) Console.WriteLine("arr({0}) : {1}", i, arr(i)) Next実行結果は以下の通りです。
arr(0) : 20190801
分解する文字列にはスラッシュは無いので、元の文字列が要素が1個の配列の先頭に返されます。
これは少し、問題が有りまして、例えば分解すべき文字列がテキストボックスか何かで入力する場合、 スラッシュで分解された配列が3個だと固定で考えて組んでしまうと、エラーが発生するはずです。 それが、以下の様な例です。'文字列を「TextBox1」から取るとする Dim strTest As String = Me.TextBox1.Text '"/"(スラッシュ)で分解する Dim arr As String() = strTest.Split("/") '3個の配列で「arr」には入る Dim strYMD As String = arr(0) + arr(1) + arr(2) Console.WriteLine("日付 : {0}", strYMD)「TextBox1」に「2019/08/01」等のスラッシュがあるデータが入力されればいいのですが、 「20190801」と入力すると、日付の連結のところでエラーが発生します。
このエラーを回避するには、分解された文字列配列の個数をチェックする方法があります。
または、テキストボックスでは無く必ず日付文字列が返されるであろう日付型コントロールを使うのも一つです。
Split には同じ名前で別の引数を持つメソッドがあります。 以下の例は、分解文字を配列で与えるメソッドです。 「/」(スラッシュ)「 」(スペース)「:」(コロン)を文字配列で与えることで、年月日時刻を一括で分解することが出来ます。'文字列の分解の例(年月日を例とする) Dim strTest As String = "2019/08/01 13:15:47" '"/"(スラッシュ)で分解する Dim arrSplit As Char() = {"/"c, " "c, ":"c} Dim arr As String() = strTest.Split(arrSplit) '3個の配列で「arr」には入る For i As Integer = 0 To UBound(arr) Console.WriteLine("arr({0}) : {1}", i, arr(i)) Next実行結果は以下の通りです。
arr(0) : 2019 arr(1) : 08 arr(2) : 01 arr(3) : 13 arr(4) : 15 arr(5) : 47
関連する記事
⇒文字列の連結をStringBuilderで高速に行う(StringBuilder)
⇒文字列定数(改行、タブ、バックスペース等)について
⇒文字列変換関数(StrConv)で変換が途中で切れる
⇒文字列変換関数(StrConv)の使い方