none
一定範囲内での分子分母の合計値が最小になるプログラムの作成。その2 RRS feed

  • 質問

  • 以前、このタイトルで質問させていただいたものです。その中のご回答の一つとしてModule Module1から始まる下記のコードを頂きました。

    そこで恐れ入りますが、更に質問させていただきますが、ご回答の一つであるModule Module1から始まる下記のコード内容を

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        End Sub

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    ....

     XC = ((1201 * Val(TextBox1.Text)) / Val(TextBox6)) - (12.01 * Val(TextBox1.Text) + 1.008 * Val(TextBox2.Text) + 16.0 * Val(TextBox3.Text) + 14.01 * Val(TextBox4.Text)) / 2.016
     XN = ((1401 * Val(TextBox1.Text)) / Val(TextBox8)) - (12.01 * Val(TextBox1.Text) + 1.008 * Val(TextBox2.Text) + 16.0 * Val(TextBox3.Text) + 14.01 * Val(TextBox4.Text)) / 2.016

    という上記の形で私がプログラミングしている最中の中に自然な形で組み込むにはどのようなコードにすればよろしいでしょうか?

    ちなみにDebug.Print("{0}", Compute(0.259, 0.895))の名の数字がXCとXNの値に置き換えさせていただきます。

    あと負の値や0であると教えてくださったコードが上手く起動しなかったので、とりあえずXCやXNがもし負の値や0の時に0.0001に置き換えて

    から計算するようにしたいです。

    計算結果はlabel5に出力させて頂く予定となります。

    以下に教えてくださった下記のコード

    Module Module1 Sub Main() Debug.Print("{0}", Compute(0.259, 0.895)) Debug.Print("{0}", Compute(0.894, 0.895)) Debug.Print("{0}", Compute(0.895, 0.895)) Debug.Print("{0}", Compute(10000, 10001)) End Sub Class Result Public Sub New(ByVal i As Integer, ByVal j As Integer) Me.I = i Me.J = j End Sub Public Property I As Integer Public Property J As Integer Public Overrides Function ToString() As String Return String.Format("{0}/{1}", I, J) End Function End Class Function Compute(ByVal min As Double, ByVal max As Double) As Result If min > max Then Return Compute(max, min) End If Dim j As Integer = 1 Do Dim i As Integer = CInt(Int(j * min)) Do ' i / j > max If i > max * j Then Exit Do ' i / j >= min ElseIf i >= min * j Then Return New Result(i, j) End If i += 1 Loop j += 1 Loop End Function End Module

    結果

    1/2
    17/19
    179/200
    10000/1
    2019年5月7日 12:10

すべての返信

  • あー、たしかにゼロと1未満の組み合わせはおかしいですね。
    収束を早めようとしたのが裏目に出てしまいました。

    申し訳ないのですが
                Dim i As Integer = CInt(Int(j * min))
    
    のあとに
                If i = 0 Then
                    i = 1
                End If
    

    を入れてください。

    >> とりあえずXCやXNがもし負の値や0の時に0.0001に置き換えて
    >> から計算するようにしたいです。

    さすがにここは・・・

    あと、両方がゼロだったときは収束しませんので、それも含めて考えてみてください。


    2019年5月7日 13:24
  • ご回答ありがとうございました。参考にさせていただきます。あと、申し上げにくいのですが、前回教えてくださったコードは新しく作成したVBのコンソールアプリケーションで起動したことは確認できましたが、今回の質問の本題は作成途中のGUIアプリケーションにどのようにして組み込むかとなります。最低限のクラスの知識などはあるつもりですが、できることならお手数をおかけしますが Debug.Printや Class Resultなどを使わずに、今作成中のForm1.vbと Form1.vb[デザイン]の二つで完結できるような

    形のコードを教えてくださいませんか?

    2019年5月8日 9:13
  • GUI アプリケーションに Module を追加することができるのですが、それはご存知でしょうか?
    追加したモジュールに Sub Main 以外を貼り付けて Form1.vb の中で

    Label5.Text = Compute(XC, XN).ToString() 

    とします。

    Form1.vb で完結したいのであれば、Sub Main 以外を Form1.vb に貼り付けてください。

    Class を使わないのであれば Compute の戻り値を String に変えて

    Return New Result(i, j) を Return String.Format("{0}/{1}", i, j) に変えた上で

    Label5.Text = Compute(XC, XN)

    という感じになるでしょう。


    2019年5月8日 10:13
  • モジュールの追加というのは盲点でした。だいぶ苦労しましたが、今日の朝になんとか良い結果が出ました。ちなみに応用としてXCのVal(TextBox6.Text)など一部の数字に+-0.3の範囲計算する予定なのですが可能でしょうか?可能ならば、どういじればよいか教えてもらえませんか?
    2019年5月11日 2:12
  • 同じ処理なら関数にしましょう。イメージはこんな感じです。

    XC = Calc(Val(TextBox6.Text))
    XC1 = Calc(Val(TextBox6.Text) + 0.3)
    XC2 = Calc(Val(TextBox6.Text) - 0.3)
    


    2019年5月11日 16:01
  • ありがとうございました。参考にさせていただきます。
    2019年5月14日 10:28
  • 「お客様の投稿にフラグが付けられ、現在、確認が行われています。 誤ってフラグが付いたと思われる場合は、スレッドの ここ に投稿してください」という文章で質問ができなくなったので恐れながらここで質問させて頂いたます。Visual Basicでの主に不等式についての質問をいくつかさせていただきます。プログラミングの途中で


    val(TextBox11.Text)-0.3≦12.01*Val(TextBox1.Text)/18.016*X+12.01*(TextBox1.Text)+...+32.07*(TextBox10.Text)≦val(TextBox11.Text)+0.3

    のような不等式でXの範囲を計算することが必要となります。一次方程式の場合はX=....の形に変えてコードを打ち込めばのいいのですが不等式の場合は÷ときに負の値かどうかで不等式の向きが変わるので、今までの方程式のやり方が通用しなくなりました。上述の式でXの範囲を計算するにはどのようなにすればよろしいでしょうか?上述の式を変形させて、左辺と中辺の式,中辺と右辺の式に分解して入力することになっても大丈夫です。

    二つ目の質問です。上述の式に似た式をあと二つ計算し、最終的に6種類のXの範囲を計算することになることになるのですが、六種類のXの範囲が重なる場合はをA≦X≦Bとして次の計算に活用、重ならない場合は解なしとして処理したいのです。そこで、六種類のXの範囲の一つのXの範囲に纏めるコードを教えてくださいませんか?因みに計算結果のAとBは、その範囲内で分子と分母の合計値が最小になる値が導き出すコードの計算で利用し、最終的に出た値を指定先のラベルに出力する予定となります。

    2019年5月15日 11:08
  • 一つ目の質問については、値が正のときと負のときで場合分けするだけだと思います。
    If 文ってわかりますよね?

    二つ目の質問については、たとえば範囲を表すクラスを作って

    Class Range
    
        Private _Min As Double
        Private _Max As Double
    
        Public Sub New(min As Double, max As Double)
            _Min = min
            _Max = max
        End Sub
    
        Public ReadOnly Property Min As Double
            Get
                Return _Min
            End Get
        End Property
    
        Public ReadOnly Property Max As Double
            Get
                Return _Max
            End Get
        End Property
    
        Public ReadOnly Property IsEmpty As Boolean
            Get
                Return Max < Min
            End Get
        End Property
    
        Public Overrides Function ToString() As String
            If IsEmpty Then
                Return "範囲なし"
            Else
                Return String.Format("{0}~{1}の範囲です。", Min, Max)
            End If
        End Function
    
        Public Shared Infinity As New Range(Double.MinValue, Double.MaxValue)
    
        Public Function Intersect(r As Range) As Range
            Return Intersect(Me, r)
        End Function
    
        Public Shared Function Intersect(r1 As Range, r2 As Range) As Range
            Return New Range(Math.Max(r1.Min, r2.Min), Math.Min(r1.Max, r2.Max))
        End Function
    
    End Class
    

    # 自動プロパティを使えば、もう少し簡単に書けますがバージョンが不明なので

    Dim r1 As New Range(1, 3)
    Dim r2 As New Range(2, 4)
    Dim r3 As New Range(5, 6)
       ・
       ・
       ・
    
    Dim result As Range = Range.Infinity
    result = result.Intersect(r1)
    result = result.Intersect(r2)
    result = result.Intersect(r3)
       ・
       ・
       ・
    

    のような感じで計算していけばよいと思います。

    2019年5月15日 16:10
  • ご回答ありがとうございました。IfでVal(TextBo11.Text)が0.3よりも大きいか小さいかで不等式の向きの問題は大丈夫そうです。大丈夫そうなんですが、

    Dim X as single とおいて

    X=((12.01 * Val(TextBox1.Text)) / (18.016 * (TextBox11.Text) ..

    とおいたら自動的にXを求めてくれるのですが、

    X<((12.01 * Val(TextBox1.Text)) / (18.016 * (TextBox11.Text) ..

    とおいても、要素に終了タグがありませんとなってうまくいかないです。

    簡潔にXの範囲をもとめるにはどのようなコードを書き込めばよろしいでしょうか

    2019年5月16日 0:28
  • 範囲というからには、最小値と最大値があるわけです。
    一回の計算では求められません。

    min = 最小値を求める計算式
    max = 最大値を求める計算式

    という2つの計算が必要です。

    で、求めた値を

    Dim r1 As New Range(min, max)

    として、Range クラスに格納します。

    これと同様に r2 ~ r6 まで作った上で Intersect メソッドで交点を求めていくことになるかと思います。
    2019年5月16日 4:08
  • なるほど、Range クラスは盲点でした。要するに

    Dim X as single 

    X<((12.01 * Val(TextBox1.Text)) / (18.016 * (TextBox11.Text) ..

    If Val(TextBo11.Text)>0.3 Then

    X>・・・Else

    X<・・・

    のようなコードは無理で

    すこし粗がありますが、下記のコードを入力すべきということでよろしいでしょうか。

    Dim X as single 

    Dim r1 As New Range(min, max)

    X=((12.01 * Val(TextBox1.Text)) / (18.016 * (TextBox11.Text) ..

    If If Val(TextBo11.Text)>0.3 Then

    r1=(-∞,X)

    Else

    r1=(X,∞)

    2019年5月16日 10:54
  • >>すこし粗がありますが、下記のコードを入力すべきということでよろしいでしょうか。

    どういうコードを書こうとしているのか、私にはさっぱりわからないのですが、実現したいことができるならそれで良いのでは?

    2019年5月16日 13:55
  • Intersect メソッドについて調べましたがよくわかりませんでした。これは要するに、Form1 Classで

        Dim XC1 As Single
            Dim XC2 As Single
            Dim r1 As New Range(XC2, XC1)

            If Val(TextBox11) > 0.3 Then
                XC1 = ((12.01 * Val(TextBox1.Text) * 100) / (18.016 * (TextBox11.Text) - 0.3)) - ((12.01 * (TextBox1.Text) + 1.008 * (TextBox2.Text) + 14.01 * (TextBox3.Text) + 16.0 * (TextBox4.Text) + 19.0 * (TextBox5.Text) + 35.45 * (TextBox6.Text) + 79.9 * (TextBox7.Text) + 129.6 * (TextBox8.Text) + 30.97 * (TextBox9.Text) + 32.07 * (TextBox10.Text)) / 18.016)
                XC2 = ((12.01 * Val(TextBox1.Text) * 100) / (18.016 * (TextBox11.Text) + 0.3)) - ((12.01 * (TextBox1.Text) + 1.008 * (TextBox2.Text) + 14.01 * (TextBox3.Text) + 16.0 * (TextBox4.Text) + 19.0 * (TextBox5.Text) + 35.45 * (TextBox6.Text) + 79.9 * (TextBox7.Text) + 129.6 * (TextBox8.Text) + 30.97 * (TextBox9.Text) + 32.07 * (TextBox10.Text)) / 18.016)

            Else
                '実質的に計算せずに他の4種の範囲のみの重なり部分のみ利用する。
                XC1 = 1000
                XC2 = 0.001

            End If

            Dim XH1 As Single
            Dim XH2 As Single
            Dim r2 As New Range(XH2, XH1)

            If Val(TextBox12) > 0.3 Then

                XH1 = ((1.008 * Val(TextBox2.Text) * 100) / (18.016 * (TextBox12.Text) - 0.3)) - ((12.01 * (TextBox1.Text) + 1.008 * (TextBox2.Text) + 14.01 * (TextBox3.Text) + 16.0 * (TextBox4.Text) + 19.0 * (TextBox5.Text) + 35.45 * (TextBox6.Text) + 79.9 * (TextBox7.Text) + 129.6 * (TextBox8.Text) + 30.97 * (TextBox9.Text) + 32.07 * (TextBox10.Text)) / 18.016)
                XH2 = ((1.008 * Val(TextBox2.Text) * 100) / (18.016 * (TextBox12.Text) + 0.3)) - ((12.01 * (TextBox1.Text) + 1.008 * (TextBox2.Text) + 14.01 * (TextBox3.Text) + 16.0 * (TextBox4.Text) + 19.0 * (TextBox5.Text) + 35.45 * (TextBox6.Text) + 79.9 * (TextBox7.Text) + 129.6 * (TextBox8.Text) + 30.97 * (TextBox9.Text) + 32.07 * (TextBox10.Text)) / 18.016)

            Else
                XH1 = 1000
                XH2 = 0.001
            End If

            Dim XN1 As Single
            Dim XN2 As Single
            Dim r3 As New Range(XN2, XN1)

            If Val(TextBox13) > 0.3 Then

                XN1 = ((14.01 * Val(TextBox3.Text) * 100) / (18.016 * (TextBox12.Text) - 0.3)) - ((12.01 * (TextBox1.Text) + 1.008 * (TextBox2.Text) + 14.01 * (TextBox3.Text) + 16.0 * (TextBox4.Text) + 19.0 * (TextBox5.Text) + 35.45 * (TextBox6.Text) + 79.9 * (TextBox7.Text) + 129.6 * (TextBox8.Text) + 30.97 * (TextBox9.Text) + 32.07 * (TextBox10.Text)) / 18.016)
                XN2 = ((14.01 * Val(TextBox3.Text) * 100) / (18.016 * (TextBox12.Text) + 0.3)) - ((12.01 * (TextBox1.Text) + 1.008 * (TextBox2.Text) + 14.01 * (TextBox3.Text) + 16.0 * (TextBox4.Text) + 19.0 * (TextBox5.Text) + 35.45 * (TextBox6.Text) + 79.9 * (TextBox7.Text) + 129.6 * (TextBox8.Text) + 30.97 * (TextBox9.Text) + 32.07 * (TextBox10.Text)) / 18.016)

            Else
                XN1 = 1000
                XN2 = 0.001


            End If

    Dim r1 As New Range(XC2, XC1) Dim r2 As New Range(XH2, XH1) Dim r3 As New Range(XN2, XN1) Dim result As Range = Range.Infinity result = result.Intersect(r1) result = result.Intersect(r2) result = result.Intersect(r3)

    とおくとXC1≦X≦XC2 XN1≦X≦XN2 XN1≦X≦XN2 の範囲から 重なる部分を調べることができるという意味でしょうか?

    例)1≦X≦100  2≦X≦50 3≦X≦75 ならば 3≦X≦50 という値が計算できる。因みにVB2017です。

    もちろんこの場合は前に教えてくださった他のClass Range を作成します。おそらくはMinとMAXの部分がr1 r2 r3の分

    Class Range1,2,3と三種類追加すればよろしいのでしょうか?ちなみに自動実装プログラムは使えます。

    2019年5月17日 12:33
  • >>とおくとXC1≦X≦XC2 XN1≦X≦XN2 XN1≦X≦XN2 の範囲から 重なる部分を調べることができるという意味でしょうか?

    はい、そうです。

    ただ、XC2 や XC1 を計算した後に Dim r1 As New Range(XC2, XC1) としてください。

    >> Class Range1,2,3と三種類追加すればよろしいのでしょうか?ちなみに自動実装プログラムは使えます。

    クラスを追加する必要はありません。
    文字を表す変数を作成するために String1, 2, 3 というクラスは作らないですよね?


    2019年5月17日 13:38
  • こんな遅くにご対応してくださりありがとうございました。

    Public Class Range
        Private _CX1 As Single
        Private _CX2 As Single

        Public Sub New(CX1 As Single, CX2 As Single)
            _CX1 = CX1
            _CX2 = CX2
        End Sub

        Public Porpaty

    と書き始めているのですが、どのコードを繰り返し、どのコードををそのまま書き下せばいいのか教えてくださいませんか?

    2019年5月17日 15:08
  • Range クラスに手を入れる必要はないのですが、何をやろうとしていますか?

    数値を Double で扱っているのが気に入らないのであれば、As Double と書いてあるのを As Single に変えるだけです。

    2019年5月17日 22:15
  • single か double かにはこだわってません。強いて言えば参考書がsingleで統一されただけなので。

    以前の質問で、二つ目の質問については、たとえば範囲を表すクラスを作ってと書いてあったのでなんか勘違いしておりました。

    あと普通に Form class内で特に別のClassタブを用意する必要がなく

    ・・・・・・・・

    XN2=0.001

    End If

    Dim r1 As New Range(XC2, XC1) Dim r2 As New Range(XH2, XH1) Dim r3 As New Range(XN2, XN1) Dim result As Range = Range.Infinity result = result.Intersect(r1) result = result.Intersect(r2) result = result.Intersect(r3)

    コード入力するだけなのか?

    それとも別のClass Range タブを作る必要がなくForm Class 内で

    以前の質問で、二つ目の質問...でのコード(Class Range..... End Function End Class)を

    XN2=0.001

    End If

    の次に打ち込み、(最終的に Dim r1 As New Range(XC2, XC1)・・・result = result.Intersect(r3))

    と打ち込めばよいという意味なのかどちらでしょうか?

        

    2019年5月18日 0:02
  • 「別のClass Range タブ」ってなんのことでしょうか?

    >>と打ち込めばよいという意味なのかどちらでしょうか?

    質問の意味がわかりません。


    2019年5月18日 1:20
  • 右端のソリューションエクスプローラーにて、追加→クラスを→名前の入力(今回の場合はRangeと入力)するという意味です。

    そのようなことをせずに、Form上のボタンをダブルクリックしてできた、public class Form1のみでのコードの入力で

    大丈夫でしょうかという意図で質問致しました。

    もし大丈夫でしたら

    ・・・・・・・・

    XN2=0.001

    End If

    Dim r1 As New Range(XC2, XC1) Dim r2 As New Range(XH2, XH1) Dim r3 As New Range(XN2, XN1) Dim result As Range = Range.Infinity result = result.Intersect(r1) result = result.Intersect(r2) result = result.Intersect(r3)

    と上記のコードをのみで重なる部分を調べることができますか?事前教えてくださった

    Class Range
    
        Private _Min As Double
        Private _Max As Double
    
        Public Sub New(min As Double, max As Double)
            _Min = min
            _Max = max
        End Sub
    
        Public ReadOnly Property Min As Double
            Get
                Return _Min
            End Get
        End Property
    
        Public ReadOnly Property Max As Double
            Get
                Return _Max
            End Get
        End Property
    
        Public ReadOnly Property IsEmpty As Boolean
            Get
                Return Max < Min
            End Get
        End Property
    
        Public Overrides Function ToString() As String
            If IsEmpty Then
                Return "範囲なし"
            Else
                Return String.Format("{0}~{1}の範囲です。", Min, Max)
            End If
        End Function
    
        Public Shared Infinity As New Range(Double.MinValue, Double.MaxValue)
    
        Public Function Intersect(r As Range) As Range
            Return Intersect(Me, r)
        End Function
    
        Public Shared Function Intersect(r1 As Range, r2 As Range) As Range
            Return New Range(Math.Max(r1.Min, r2.Min), Math.Min(r1.Max, r2.Max))
        End Function
    
    End Class
    の扱いがよくわからなくて。困っています。

    2019年5月18日 1:43
  • クラスは、参照できる位置にあれば、どこにあっても構いません。

    コードの再利用を考えるのであれば、別のファイルにしたほうがいいと思います。

    2019年5月18日 13:24