質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.36%

  • VBA

    1898questions

    VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

VBAを使って抵抗率補正係数を求めたい

受付中

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 270

tks522

score 1

VBAを用いて下記に添付したRCF(抵抗率補正係数)を求める計算プリグラムを作成したい。

(a=1cm , b=1cm , t=100nm , (xa , xb , xc , xd)=(0, 0.1 ,0.2 ,0.3), (ya , yb , yc , yd)=0 )

抵抗率補正係数

以下、作成したプログラムです。
いろいろ変えてみてcoshやsinhやP8でオーバーフローしてしまいます。
expの中身が710を超えるとオーバーフローしてしまうことは既知なんですがそれを変えるために何かいい方法ありませんか。
Sub 演習()

Dim Arg1 As Double
Dim Arg2 As Double
Dim Arg3 As Double
Dim Arg4 As Double
Dim Arg5 As Double
Dim Arg6 As Double
Dim Arg7 As Double
Dim Arg8 As Double
Dim Arg9 As Double
Dim Arg10 As Double
Dim Arg11 As Double
Dim Arg12 As Double
Dim K1 As Double
Dim K2 As Double
Dim K3 As Double
Dim K4 As Double
Dim K5 As Double
Dim K6 As Double
Dim K7 As Double
Dim K8 As Double
Dim K9 As Double
Dim P1 As Double
Dim P2 As Double
Dim P3 As Double
Dim P4 As Double
Dim P5 As Double
Dim P6 As Double
Dim P7 As Double
Dim P8 As Double
Dim P9 As Double
Dim L1 As Double
Dim L2 As Double
Dim L3 As Double
Dim L4 As Double
Dim L5 As Double
Dim L6 As Double
Dim L7 As Double
Dim L8 As Double
Dim L9 As Double
Dim Q As Double
Dim m As Integer
Dim n As Integer
Dim A As Double
Dim b As Double
Dim t As Double
Dim xa As Double
Dim xb As Double
Dim xc As Double
Dim xd As Double
Dim ya As Double
Dim yb As Double
Dim yc As Double
Dim yd As Double
Dim PI As Double

A = 1000000000
b = 1000000000
t = 300
xa = 0
xb = 10000000
xc = 20000000
xd = 30000000
ya = 0
yb = 0
yc = 0
yd = 0
m = 1
n = 1
PI = 4 * Atn(1)
Q = (yb - yc) / A

K9 = 0
P9 = 0
L9 = 0

For m = 1 To 10

Arg1 = m * PI / A
Arg2 = (yb + b / 2)
Arg3 = (yc + b / 2)
Arg4 = (ya - b / 2)
Arg5 = (yb - b / 2)
Arg6 = (yc - b / 2)
Arg7 = (yd + b / 2)
Arg8 = n * PI / t
Arg9 = (Arg1) * (Arg1) + (Arg8) * (Arg8)
Arg10 = Sqr(Arg9)

K1 = 2 / m * PI * WorksheetFunction.sinh(b * Arg1)
K2 = Cos(Arg1 * xb) * WorksheetFunction.cosh(Arg1 * Arg2)
K3 = Cos(Arg1 * xc) * WorksheetFunction.cosh(Arg1 * Arg3)
K4 = Cos(Arg1 * xa) * WorksheetFunction.cosh(Arg1 * Arg4)
K5 = Cos(Arg1 * xb) * WorksheetFunction.cosh(Arg1 * Arg5)
K6 = Cos(Arg1 * xc) * WorksheetFunction.cosh(Arg1 * Arg6)
K7 = Cos(Arg1 * xd) * WorksheetFunction.cosh(Arg1 * Arg7)

K8 = K1 * ((K2 - K3) * K4 - (K5 - K6) * K7)

K9 = K9 + K8

Next m

For n = 1 To 100
Arg1 = m * PI / A
Arg2 = (yb + b / 2)
Arg3 = (yc + b / 2)
Arg4 = (ya - b / 2)
Arg5 = (yb - b / 2)
Arg6 = (yc - b / 2)
Arg7 = (yd + b / 2)
Arg8 = n * PI / t
Arg9 = (Arg1) * (Arg1) + (Arg8) * (Arg8)
Arg10 = Sqr(Arg9)
P1 = 2 / A * Arg8 * sinh(b * Arg8)
P2 = cosh(Arg8 * Arg2)
P3 = cosh(Arg8 * Arg3)
P4 = cosh(Arg8 * Arg4)
P5 = cosh(Arg8 * Arg5)
P6 = cosh(Arg8 * Arg6)
P7 = cosh(Arg8 * Arg7)

P8 = P1 * ((P2 - P3) * P4 - (P5 - P6) * P7)
P9 = P9 + P8
Next n

For m = 1 To 100
For n = 1 To 100
Arg1 = m * PI / A
Arg2 = (yb + b / 2)
Arg3 = (yc + b / 2)
Arg4 = (ya - b / 2)
Arg5 = (yb - b / 2)
Arg6 = (yc - b / 2)
Arg7 = (yd + b / 2)
Arg8 = n * PI / t
Arg9 = (Arg1) * (Arg1) + (Arg8) * (Arg8)
Arg10 = Sqr(Arg9)

L1 = 4 / A * Arg10 * WorksheetFunction.sinh(b * Arg10)
L2 = Cos(Arg1 * xb) * WorksheetFunction.cosh(Arg10 * Arg2)
L3 = Cos(Arg1 * xc) * WorksheetFunction.cosh(Arg10 * Arg3)
L4 = Cos(Arg1 * xa) * WorksheetFunction.cosh(Arg10 * Arg4)
L5 = Cos(Arg1 * xb) * WorksheetFunction.cosh(Arg10 * Arg5)
L6 = Cos(Arg1 * xc) * WorksheetFunction.cosh(Arg10 * Arg6)
L7 = Cos(Arg1 * xd) * WorksheetFunction.cosh(Arg10 * Arg7)

L8 = L1 * ((L2 - L3) * L4 - (L5 - L6) * L7)

L9 = L9 + L8

Next n
Next m

Cells(5, 5) = K9
Cells(5, 6) = P9
Cells(5, 7) = L9

End Sub

Function sinh(x As Double)
Dim A As Double
Dim i As Long
Dim G As Double
Dim H As Double
Dim K As Double
Dim J As Double

H = 1
For i = 1 To 10000000

G = Exp(x / 10000000)
H = (G * H) / 10000000

Next i

J = 1
For i = 1 To 10000000

K = Exp(-x / 10000000)
J = (J * K) / 1000

Next i

sinh = (H - J) / 2

End Function

Function cosh(x As Double)
Dim A As Double
Dim v As Long
Dim G As Double
Dim H As Double
Dim K As Double
Dim J As Double

H = 1
For v = 1 To 10000000

G = Exp(x / 10000000)
H = G * H / 1000000000

Next v

J = 1
For v = 1 To 10000000

K = Exp(-x / 10000000)
J = K * J / 10000

Next v

cosh = (H + J) / 2

End Function

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ExcelVBAer

    2018/07/05 09:45

    演習!? まさかの宿題ですか??

    キャンセル

  • ExcelVBAer

    2018/07/05 09:47

    コードは『<code>』ボタンを使って記載してください

    キャンセル

回答 3

0

取り敢えず型を揃えてみてはどうでしょうか。

全てDoubleで定義してみて下さい。
Functionの戻り値や演算で使用している数値も同様にDoubleで。

Function cosh(x As Double) As Double

Function sinh(x As Double) As Double


2だとInteger扱いですが、2#のように記述するとDoubleとして扱ってくれます。

Doubleは誤差が生じるので、問題が有るようなら、Currency型も検討してみて下さい。

追記

hatenaさんの回答を見て、cosh()やsinh()を試してみましたが、Expの限界になる前にオーバーフローしました。
exp()を使用しているのはこのfanctionだけでしたので、ここを対処すれば良いと思いますが、
無駄なロジック多いし、そもそも何してんのか不明です。幾つかパラメータの桁数を変えて確認しましたが0しか返却しませんし。

上記とは別に、VBAで処理する際、除算は誤差を生むので、行うとしてもまとめて最後で行うことを良くしますが、オーバーフローに関しても途中でオーバーフローしないように、式を分解して展開するのが必要な箇所があるのかもしれません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/05 14:42

    主さんは、710以上を引数に与えるとオバーフローになるということはわかっていて、それを超える方法はないかとの質問だと思います。
    HSin(X) = (Exp(X) - Exp(-X)) / 2
    HCos(X) = (Exp(X) + Exp(-X)) / 2
    というExpを使った簡単な式に置き換えられますのが、これを展開して、
    オーパーフローしないような式に分解できればいいのですが、どうでしょうか。

    キャンセル

  • 2018/07/05 14:55 編集

    目的は、「抵抗率補正係数を求めたい」なのであって、過程でオーバーフローが発生してなんとかしたいというのは副次的な目的と捉えています。
    hatenaさんも書かれているように、オーバーフローする数値自体が計算過程に於いて必要なのかが疑問なのです。

    function自体も意図が不明なので、回答としては、そもそもオーバーフローするような数値になってるのは、どこか誤りがあるんじゃないの?というのが回答の趣旨です。

    sinh()やcosh()は、sin()やcos()の亜種なのかと思ってsinh()やcosh()でオーバーフローする値を与えてあげても、オーバーフローしないし、幾つかのパターンを与えても結果が0というのも、どこか誤りがあるのではと思うので、今のコードのsinh()やcosh()がターゲットになるかどうかすら不明な状態です。

    キャンセル

  • 2018/07/05 15:06

    HSin(X) は (Exp(X) - Exp(-X)) / 2 に置き換えられます。下記リンク参照
    超越関数 https://msdn.microsoft.com/ja-jp/library/cc392350.aspx
    主さんの sinh() や cosh() は意味不明です。
    どちらにしても、主さんのコードに間違いがあるか、与える引数の値が間違っているかだと思ってます。

    キャンセル

  • 2018/07/05 15:22

    成程。sinh()やcosh()は、双曲線コサインや双曲線サインを求めようとしてるってことですね。
    元の数式のどこかって言われても分からないですけどw
    展開については、Exp(X) - Exp(-X)はそもそも0じゃないの?というレベルですからw、分かりません。

    キャンセル

0

expの中身が710を超えるとオーバーフローしてしまうことは既知なんですがそれを変えるために何かいい方法ありませんか。

Exp 関数

上記によると戻り値は Double です。引数に 709.782712893以上を与えるとエラーになると書いてあります。

イミディエイトウィンドウで確認

?Exp(709.782712893)
 1.7976931341721E+308 

?Exp(709.782712894)
'オバーフローエラー

Doubleを使う限りは不可能です。また、VBAでDoubleの範囲より大きい数を扱える型はありません。

1.7976931341721E+308 って308桁の数値ということです。
そのような巨大な数値以上になるということ自体が現実的でないような気がします。
抵抗率補正係数というものについては全く専門外なのであくまで感想ですが。
途中の式に間違いがないのか検討されては。

補足

下記のスレッドの続きだと思いますので、回答をつける場合は参照しておくといいかと。

VBA \- VBAを使ってsinh,coshを使いたい。\(133368\)|teratail

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

計算が得意な他の言語でやるべきじゃない?
よく分からないけど、R や Python(パイソン) とか。

あと、自作関数の cosh , sinh の処理内容を見ましたが、
やりたい事は分かるけど、計算の方針自体が違うから、
文系?って思っちゃいますよ。。。

あと、自作しても、Exp(1)で e の正確な値が
取得できないみたいなので、
誤差が出ちゃうみたいです。

それでもVBAでっていうのであれば、
Double型やCurrency型を使って、
cosh,sinh,Exp を自作する方向で頑張ってください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • VBA

    1898questions

    VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。