久しぶりの「三角関数の合成」

先日、長男(高2)の数学で、久しぶりに「三角関数の合成」と再会した。
懐かしさのあまり、復習してみた。
asinθ+bcosθ=\sqrt{a^2+b^2}sin(θ+α)
ただし角度αは、下図でいえばx軸と線分ACの成す角度とする。

この円の半径rは、三平方の定理から次のように求まる。
r=\sqrt{a^2+b^2}
また、三角比の定義によりa,bはそれぞれ以下のとおり。
a=rcosα
b=rsinα
ゆえに最初の式に戻ると、加法定理により
asinθ+bcosθ=r(sinθcosα+cosθsinα)=\sqrt{a^2+b^2}sin(θ+α)
となる。

教科書ではその後に、このような練習問題が。
\sqrt{3}sinθ+cosθ
これは、
cosα=\dfrac{a}{\sqrt{a^2+b^2}}=\dfrac{\sqrt{3}}{\sqrt{\sqrt{3}^2+1^2}}=\dfrac{\sqrt{3}}{2}
であるから、
α=\dfrac{π}{6}
となって、答えは
2sin(θ+\dfrac{π}{6})
となる。実際グラフを描いてみれば、両者はピッタリと一致する。

この問題のα(=\dfrac{π}{6})を見て、思った。誤解を恐れずに言うならば、当時はあまり
感じなかったが高校生の時って、とても丁寧に導かれてたんだなって。

参考まで。

VBA100本ノック 32本目:Excel終了とテキストファイル出力

こちらで公開されている、100本ノックに挑戦。
www.excel-ubara.com
素晴らしい教材を公開いただき、ありがとうございます。

上記リンク先から、問題文を転載。

ファイル操作などを行う際、DirとFileSystemObjectのどちらを使用すべきか?
が話題にあがるように思う。個人的にはFileSystemObjectの方が好みだ。先日
新たに知ったのだが、

FSO.BuildPath(A, B)

とすると、Aの末尾に「\」があってもなくても、良い感じにAとBを繋いで
くれる。これは便利だ。

また、テキストファイルへの書き出しは偶にしか行わないので、いつもうろ
覚えだったりする。今回は、良い復習の機会になった。

Sub VBA_100Knock_032()
    ' Microsoft Scripting Runtimeを参照済み。
    Dim FSO As Scripting.FileSystemObject
    Set FSO = New Scripting.FileSystemObject
    
    ' ログ用ファイルの作成と
    Dim LogPath As String
        LogPath = FSO.BuildPath(ThisWorkbook.Path, Format(Now, "yyyymmddhhmmss.txt"))
        FSO.CreateTextFile LogPath
        Open LogPath For Output As #1
    
    ' 起動中のブックについて、パスをログファイルに書き出したうえで上書き保存。
    Dim Wb As Workbook
        For Each Wb In Workbooks
            If Wb.Name <> ThisWorkbook.Name Then
                Print #1, Wb.FullName
                Wb.Close SaveChanges:=True
            End If
        Next
    
    ' マクロブックのパスの書出しと終了。
        Print #1, ThisWorkbook.FullName
        Close #1
        
        ThisWorkbook.Close SaveChanges:=True
    
    ' Excelの終了。
        Application.Quit
End Sub

※冒頭リンク先の解答例および解説も、ぜひご一読ください。

参考まで。

VLOOKUP関数で「0」を表示しない3つの方法

VLOOKUP関数で検索先が空欄の場合、数字の「0」が返ってしまう。

そこで、「0」を表示しない方法を以下にまとめてみた。

1. ゼロ値のセルにゼロを表示する

「ファイル」「オプション」の「詳細設定」に、
・ゼロ値のセルにゼロを表示する
というオプションがある。

このチェックを外すことで、0を表示させなくできる。

この指定はシート単位で行われるため、意図しない範囲の0まで消えて
しまうこともある(要注意)。

2. 無理矢理文字にする

VLOOKUP関数の先頭に""を追加することで、結果を文字にする。

数字だと「何もない=0」だが、文字にしてしまえば0にならない。

3. ユーザー定義書式で0を非表示にする

セルの書式設定で、ユーザー定義書式を設定することができる。
方々で解説されている通り、「;」で各書式を個別に設定可能だ。

正の数の書式;負の数の書式;ゼロの書式;文字列の書式

従って文字のみ表示したい場合、以下のように設定する。

;;;@


まとめ

以上1. ~3. をご紹介したが、きっと他にも良い方法があるに違いない。
どの方式を採用するかは各位の、時と場合とお好みで。

参考まで。

VBA100本ノック 31本目:入力規則

こちらで公開されている、100本ノックに挑戦。
www.excel-ubara.com
素晴らしい教材を公開いただき、ありがとうございます。

上記リンク先から、問題文を転載。

作成したマクロがこちら。

Sub VBA_100Knock_031()
    ' シート名リスト作成用配列。
    Dim SourceList() As Variant
    ReDim SourceList(1 To Sheets.Count)
    Dim i As Long
        For i = 1 To Sheets.Count
            SourceList(i) = Sheets(i).Name
        Next    
    
    With Range("A1").Validation
        ' 既存の入力規則を削除。
        .Delete
        ' 入力規則追加。
        .Add Type:=xlValidateList, _
             AlertStyle:=xlValidAlertStop, _
             Formula1:=Join(SourceList, ",")
        ' ドロップダウンで選択。
        .InCellDropdown = True
        ' エラー時のメッセージタイトル。
        .ErrorTitle = "入力不可"
        ' エラー時のメッセージ。
        .ErrorMessage = "こちらは選択専用セルです。"
        ' エラーの表示許可。
        .ShowError = True
    End With
End Sub

ドロップダウンを設定したことは、今までに何度かあった。しかし

.InCellDropdown = True

など、細かいプロパティについてあまり気にしたことがなかったので、
今回は良い勉強になった。

※冒頭リンク先の解答例および解説も、ぜひご一読ください。

参考まで。

久しぶりの等加速度直線運動

先日、長男(高2)の物理で、久しぶりに等加速度直線運動と再会した。
懐かしさのあまり、復習してみた。

ボールを地表から真上に、以下の条件で打ち上げたとする。
初 速:29.4 m/s
重力加速度:9.8 m/s^2
このとき、t秒後の物体の速度は?という問題。

懐かしい、基本中の基本である。
しかしこれも、馴染みない方は難問と感じるかもしれない。そんなときは問題を
こう読み替えると良いかも。

Aさんが、ある施設を利用する。
所持金:29.4円
利用料:1時間あたり9.8円
このとき、t時間後のAさんの所持金はいくらか?

答えは、まったく同じ数字になる(勿論、本質や単位等は違うが)。

これを数式にしてグラフに表すと、単純明快な問題であることが分かる。

t秒後の速度を求める式は、中学二年で習う一次関数 y=ax+b で表される。
v=-9.8t+29.4
初速は切片(b)であり、加速度は傾き (a) という訳だ。3秒後には速度0となって
ボールは最高到達点に達し、今度は地面に向かって落ちてくる。上向きの速度を
+で考えるなら、下向きの速度は-となる。

小学生の時、距離と速度と時間の関係を習った。
距離=速度×時間
このグラフを見ると、横軸が時間で縦軸が速度であるから、面積が距離となる。

上記台形の面積の求め方は、小学校の時習った。
面積=(上底+下底)×高さ÷2
=(29.4-9.8t+29.8)×t÷2=-4.9t^2+29.8t
これは中学三年生で習う、上に凸な放物線だ。

縦軸が距離だから、この放物線はt秒後のボールの地面からの高さを示している。
この場合は3秒後に44.1mまで届き、6秒後に地面に落ちることがわかる。

ちなみにt秒後の速度は、この放物線の接線の傾きに等しい。実際、先程の距離の
式を時間で微分すると、最初に示した速度の式になる。例えば2秒後の接線を書き
加えると、こんな感じになる。微分は、理系なら高校二年で習う(?)。

この接線の傾きが、この時の速度に等しい。今にして思えば、これまた単純明快な
話だが、現役の頃は深く理解できてなかった気がする。
今から一通り学び直すのも、面白いかもしれない。

参考まで。

久しぶりの加法定理

5月の連休中に長男(高2)の数学で、久しぶりに加法定理と再会した。

sin(α±β)=sinαcosβ±cosαsinβ
cos(α±β)=cosαcosβ∓sinαsinβ

これを用いると、↓のようなお絵かきマクロに必要な値を求めることができる。

点Pを中心に点Q1を β° 回転させたときの点Q2の座標。

まず、基本に立ち返ってみる。下図においては、定義により次が成立する。

\dfrac{x}{r}=cosθ,  \dfrac{y}{r}=sinθ
両辺にrを掛けて、
x=rcosθ, y=rsinθ

では、この場合はどうだろう。

Q1がx軸からα回転したものであるとき、Q2はx軸からα+β回転するわけだから、
先程の結果から考えると以下が成立する。
qx_{\mathrm{2}}=px+rcos(α+β), qy_{\mathrm{2}}=py+rsin(α+β)

ここで加法定理を用いると、次のように変形できる。
qx_{\mathrm{2}}=px+rcos(α+β)=px+rcosαcosβ-rsinαsinβ=px+dxcosβ-dysinβ
qy_{\mathrm{2}}=py+rsin(α+β)=py+rsinαcosβ+rcosαsinβ=py+dycosβ+dxsinβ
角度αを求めなくとも、
rcosα=dx, rsinα=dy
であるから、加法定理の中身からαに関する部分が消えて、そこそこシンプルに
なってくれるわけで。

ということで、例えば ↓ こんな具体例で、Q2の座標を求めてみよう。

結果がこちら。多分、合ってると思う。

参考まで。

組合せ表を作る 2.重複を認めない

先日は、部品1~部品4が各々AからCの何れかの値を取り得るとき、
その全ての組合せ表を作ることに挑戦した。
infoment.hatenablog.com

今回は、A~CではなくA~Dの何れかの値を取るものとして、
それらが重複しない場合のみの組合せ表を作成してみよう。

重複しないのだから、例えば
・AAAA
・AABC
のように、同じ文字が二つ以上含まれるものは除外される。
・ABCD
・BCAD
のように、全ての文字が含まれる場合のみ残るわけだ。

重複を許さないということで、お馴染みの辞書(連想配列)を用いて
マクロで作成するなら、例えばこんな感じだろうか。

Sub Sample()
    Dim i As Long
    Dim j As Long
    Dim k As Long
    Dim l As Long
    Dim arr(0 To 4 ^ 4, 1 To 5)
    Dim counter As Long
    Dim Dict As Scripting.Dictionary
    Set Dict = New Dictionary
    
        ' ラベル行データ作成。
        arr(0, 1) = "No."
        arr(0, 2) = "部品1"
        arr(0, 3) = "部品2"
        arr(0, 4) = "部品3"
        arr(0, 5) = "部品4"
        
        ' ボディ部のデータ作成。
        ' "A"が、Chr関数でChr(65)であることを利用している。
        For i = 1 To 4
            For j = 1 To 4
                For k = 1 To 4
                    For l = 1 To 4
                        ' i~lを辞書に登録し、重複がない場合のみ登録する。
                        Dict(i) = i
                        Dict(j) = j
                        Dict(k) = k
                        Dict(l) = l
                        If UBound(Dict.Keys) = 3 Then
                            counter = counter + 1
                            arr(counter, 1) = counter
                            arr(counter, 2) = Chr(i + 64)
                            arr(counter, 3) = Chr(j + 64)
                            arr(counter, 4) = Chr(k + 64)
                            arr(counter, 5) = Chr(l + 64)
                        End If
                        Dict.RemoveAll
        Next l, k, j, i
        
        ' 値貼り付け。
        Range("A1").Resize(counter + 1, 5) = arr
End Sub

今回は重複チェックで辞書を使っているので、前回よりさらに手間が増えている。
※きっと、もっとスマートな方法があるに違いない。

そこで前回同様、関数で対応することを考えてみた。
※しつこいようだが恐らく、これも既に広く知られている手法と思う。

まず前回同様、関数で組合せ表を作成する。

ここにもう一列追加して、部品1~部品4までの文字種類数を数える。
なお、SUMPRODUCT関数とCOUNTIF関数を組み合わせたこの方法は、
様々なサイトで紹介されているので、そちらを参照してほしい。

あとは、文字種類数が4のものでフィルタをかければよい。

前回に増して万人受けしないものが出来てしまったが、やはり個人的に
嫌いではない。もし採用され場合は、時と場合と各位のお好みで。

参考まで。