SSブログ

[Algo]和と積から元の2数の算出 [Programming Algorithm]

[はじめに]
(1)ある2数の和と積から、元の2数を求めるアルゴリズムです。
   例えば、『足して5』、『掛けて6』になる2つの数は、
   になります。
   これを解くアルゴリズムとして、
   2次方程式の解の解法を利用することができます。

   具体的には、
   Xについての2次方程式
   2-5X+6=0 は因数分解すると、
   (X-2)(X-3)=0 となり、
   解はX=2、3 となります。

   つまり、
   2-(α+β)X+αβ=0 の解が、
   X=α、β となることを利用することで、
   元の2数を求めることができます。

   α+β=Aαβ=Bとした時、
   2次方程式の解の公式から、
   2-AX+B=0 
   X= {A±(A2 - 4B)1/2} / 2 となり、 
   求める2数は、
   X= {A+(A2 - 4B)1/2} / 2 と
   X= {A-(A2 - 4B)1/2} / 2
   となります。

   また、2次方程式の判別式が負数の場合、
   つまり2次方程式の実数解が存在しない場合は、
   元の2数が存在しないので、解を算出する前にチェックする必要があります。

[参考]2次方程式の解の公式
E784A1E9A18C.jpg
[ソース]
''' <summary>
''' 和(α+β)と積(α×β)から、αとβを算出する。
''' </summary>
''' <param name="sum">和(α+β)</param>
''' <param name="product">積(α×β)</param>
''' <returns>αとβ(存在しない場合はNothing)</returns>
''' <remarks></remarks>
Public Shared Function CalcValueBySumProduct(ByVal sum As IntegerByVal product As IntegerAs Decimal()
    'α、βの算出に
    '2次方程式の解の公式を利用する。
    '   以下の2次方程式を解くと、X=α、βになることを利用して、
    '   X*X - (α+β)*X + α*β = 0
    '   を解く。
    '   X= [(α+β)±√{(α+β)*(α+β) - 4*α*β}] / 2
    '補足
    '   実数解が存在しない場合は、解が存在しないものとする。
    Dim dist As Decimal = sum * sum - 4 * product

    If dist < 0 Then
        Return Nothing
    End If

    Dim sqrtDist As Decimal = Math.Sqrt(dist)
    Dim rtnValue() As Decimal = New Decimal(1) {}
    rtnValue(0) = (sum - sqrtDist) / 2
    rtnValue(1) = (sum + sqrtDist) / 2

    Return rtnValue
End Function
[VB.NET]和と積から元の2数を算出する。

[.NET]Imageの分割 [Programming .NET Tips]

ファイルから取り込んだImageを複数に分割する機会があったので、
作ってみました。

[ポイント]
(1)Imageオブジェクトを指定した個数で分割します。
   例:縦5個、横10個と指定すると、5×10の2次元配列でImageを作成します。
(2)Imageを分割するには、
   Graphics.DrawImage(Image, Integer, Integer, Rectangle, GraphicsUnit)
   を使います。
(3)参考文献
   『MSDN Library for VisualStudio2008日本語版』

[ソース]
''' <summary>
''' 指定したImageを分割する。
''' </summary>
''' <param name="originalImage">オリジナルImage</param>
''' <param name="verticalNum">分割数(垂直)</param>
''' <param name="horizontalNum">分割数(水平)</param>
''' <returns>分割済Image</returns>
''' <remarks></remarks>
Public Shared Function DivideImage( _
    ByVal originalImage As Image, _
    ByVal verticalNum As IntegerByVal horizontalNum As Integer _
    ) As Image()()

    '引数チェック
    If originalImage Is Nothing Then
        Throw New ArgumentNullException("originalImage is null")
    End If

    If verticalNum < 1 Then
        Throw New ArgumentOutOfRangeException("verticalNum < 1")
    End If

    If horizontalNum < 1 Then
        Throw New ArgumentOutOfRangeException("horizontalNum < 1")
    End If

    Dim g As Graphics = Nothing

    Dim rtnImage()() As Image = New Image(verticalNum - 1)() {}
    For i As Integer = 0 To verticalNum - 1
        rtnImage(i) = New Image(horizontalNum - 1) {}
    Next

    Dim originalSize As Size = originalImage.Size
    Dim divWidth As Integer = originalSize.Width / horizontalNum
    Dim divHeight As Integer = originalSize.Height / verticalNum

    For vCnt As Integer = 0 To verticalNum - 1
        For hCnt As Integer = 0 To horizontalNum - 1
            Try
                '空のImageを作成
                rtnImage(vCnt)(hCnt) = New Bitmap(divWidth, divHeight)
                'Imageを描画する為のGraphicsオブジェクトを作成
                g = System.Drawing.Graphics.FromImage( _
                       rtnImage(vCnt)(hCnt))
                'オリジナルImageから描画対象の領域を算出
                '[補足]
                '   領域の開始座標を
                '   ・hCnt * divWidth
                '   ・vCnt * divHeight
                '   ではなく、
                '   ・hCnt * originalSize.Width / horizontalNum
                '   ・vCnt * originalSize.Height / verticalNum
                '   にしているのは、誤差を軽減する為です。
                Dim rect As New Rectangle( _
                    hCnt * originalSize.Width / horizontalNum, _
                    vCnt * originalSize.Height / verticalNum, _
                    divWidth, _
                    divHeight _
                    )
                'オリジナルImageの内容を描画
                g.DrawImage( _
                     originalImage, 0, 0, rect, GraphicsUnit.Pixel)
            Finally
                If Not (g Is NothingThen
                    'Graphicsオブジェクトを解放
                    g.Dispose()
                End If
            End Try
        Next
    Next

    Return rtnImage
End Function
[VB.NET]Imageを分割する例


/// <summary>
/// 指定したImageを分割する。
/// </summary>
/// <param name="originalImage">オリジナルImage</param>
/// <param name="verticalNum">分割数(垂直)</param>
/// <param name="horizontalNum">分割数(水平)</param>
/// <returns>分割済Image</returns>
/// <remarks></remarks>
public static Image[][] DivideImage(
    Image originalImage, int verticalNum, int horizontalNum)
{
    
    //引数チェック
    if (originalImage == null) {
        throw new ArgumentNullException("originalImage is null");
    }
    
    if (verticalNum < 1) {
        throw new ArgumentOutOfRangeException("verticalNum < 1");
    }
    
    if (horizontalNum < 1) {
        throw new ArgumentOutOfRangeException("horizontalNum < 1");
    }
    
    Graphics g = null;
    
    Image[][] rtnImage = new Image[verticalNum][];
    for (int i = 0; i <= verticalNum - 1; i++) {
        rtnImage(i) = new Image[horizontalNum];
    }
    
    Size originalSize = originalImage.Size;
    int divWidth = originalSize.Width / horizontalNum;
    int divHeight = originalSize.Height / verticalNum;
    
    for (int vCnt = 0; vCnt < verticalNum ; vCnt++) {
        for (int hCnt = 0; hCnt < horizontalNum ; hCnt++) {
            try {
                //空のImageを作成
                rtnImage(vCnt)(hCnt) = new Bitmap(divWidth, divHeight);
                //Imageを描画する為のGraphicsオブジェクトを作成
                g = System.Drawing.Graphics.FromImage(
                    rtnImage(vCnt)(hCnt));
                //オリジナルImageから描画対象の領域を算出
                //[補足]
                // 領域の開始座標を
                // ・hCnt * divWidth
                // ・vCnt * divHeight
                // ではなく、
                // ・hCnt * originalSize.Width / horizontalNum
                // ・vCnt * originalSize.Height / verticalNum
                // にしているのは、誤差を軽減する為です。
                Rectangle rect = new Rectangle(
                     hCnt * originalSize.Width / horizontalNum, 
                     vCnt * originalSize.Height / verticalNum, 
                     divWidth, divHeight);
                //オリジナルImageの内容を描画
                g.DrawImage(
                    originalImage, 0, 0, 
                    rect, GraphicsUnit.Pixel);
            }
            finally {
                if (g != null) {
                    //Graphicsオブジェクトを解放
                    g.Dispose();
                }
            }
        }
    }
    
    return rtnImage;
}
[C#]Imageを分割する例

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。