先日書いたコードで気になった部分が1点。
Sub 画像トリム() leftCutSize = 40 With Selection.ShapeRange OriginalWidth = .Width .LockAspectRatio = msoFalse .ScaleWidth (OriginalWidth - leftCutSize) / OriginalWidth, msoFalse, msoScaleFromBottomRight .PictureFormat.Crop.PictureWidth = OriginalWidth .PictureFormat.Crop.PictureOffsetX = leftCutSize / 2 * -1 End With End Sub
ScaleWidthメソッドの第一引数である。
(OriginalWidth - leftCutSize) / OriginalWidth
これって分配法則が成り立つんだったかな。
こう?
(OriginalWidth / OriginalWidth) - (leftCutSize / OriginalWidth)
ということはこう?
1 - (leftCutSize / OriginalWidth)
普段計算してないもんだから、こんなことまで忘れてしまう。
ネットで調べてみようかなと思う前に、コードが閃いた。
そうだ、試そう。
Sub test() For a = 1 To 100 For b = 1 To 100 Debug.Print (a - b) / a = 1 - (b / a) Next b, a End Sub
結果は、TrueとFalseが半々。
あれ?と思って変数の型を疑ってみた。
Sub test() Dim a As Double, b As Double For a = 1 To 100 For b = 1 To 100 If Not (a - b) / a = 1 - (b / a) Then Debug.Print False Next b, a Debug.Print "Finish" End Sub
これでも14個のFalseが発生。
両辺をDecimal型にしてやったらFalseが出なくなった。
Sub test() Dim a As Double, b As Double For a = 1 To 100 For b = 1 To 100 If Not CDec((a - b) / a) = CDec(1 - (b / a)) Then Debug.Print False Next b, a Debug.Print "Finish" End Sub
要は精度の問題で不一致が出ていただけで、Decimalできちんと計算すると分配法則は成立しているということが分かった。
今回のケースだとネットで調べた方が早いけれど、「理屈が分からなければ、実際に試してしまえ」ということが出来るのはプログラマの強みである。