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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

1397閲覧

C# ほぼ一定倍率で増えていく価格計算

IShix

総合スコア1729

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

1グッド

1クリップ

投稿2020/06/24 14:22

編集2020/06/28 15:40

[追記] 最終的にいただいた意見をすべて混ぜました

ku__ra__geさん、ikadzuchiさん、TN8001さん
ありがとうございました。

・ 初回ロードでMath.Powを使いキャッシュ
・ 2回目以降はキャッシュに対して計算する

Math.Powは重いとのことでしたが、計測したところ今回の使い方では早いので使うことにしました。
Macbook proにて1万回繰り返した結果
Math.Pow 0.003 秒
for 0.047 秒

コード全文

C#

1public sealed class ItemPrice 2{ 3 public int Level{ get; private set; } 4 public long Value => (long)value; 5 6 public readonly long StartPrice; 7 public readonly double PriceRate; 8 9 double value; 10 11 public ItemPrice(int level, long startPrice, double priceRate) 12 { 13 Assert.IsTrue(level > 0); 14 Assert.IsTrue(startPrice > 0); 15 Assert.IsTrue(priceRate > 0); 16 17 Level = level; 18 StartPrice = startPrice; 19 PriceRate = priceRate; 20 21 value = Load(Level, StartPrice, PriceRate); 22 } 23 24 public void Upgrade() 25 { 26 Level++; 27 value = Upgrade(value, PriceRate); 28 } 29 30 public static double Load(int level, long startPrice, double priceRate) 31 { 32 return level > 1 ? startPrice * Math.Pow(priceRate, level - 1) : startPrice; 33 } 34 35 public static double Upgrade(double currentPrice, double priceRate) => currentPrice * priceRate; 36}

実現したいこと

購入するごとに金額が増えていくアイテムがあります。
金額が増える倍率をひとつ前の価格に対して同じ倍率で増えていく計算式を探しております。
ご教授いただきたけますと幸いです。よろしくお願いいたします。

例 )
Lv1のアイテムを購入するとLv2の価格に変わる

Lv1 100円
LV2 110円 (Lv1に対して1.1倍)
LV3 121円 (Lv2に対して1.1倍)
.
.
.
Lv30 1540円 (Lv29に対して1.099957倍)

※ 整数に置き換えるので多少の誤差は問題ないと思っています。

発生している問題

ひとつ前の価格に対して掛けていくような計算であれば簡単ですが、ひとつ前の金額を保存または再計算する必要がある為初期値に対して計算したいです。

初期値に対してレベルを掛けていくような計算式を考えましたが、下記だと徐々に倍率が下がってしまいます。

C#

1public static long GetPrice(int level, long startPrice, float rate) 2{ 3 return level > 1 ? (long)(startPrice + (startPrice * rate * level)) : startPrice; 4}

計算結果
Lv1 100円
Lv2 120円 (Lv1に対して1.2倍)
Lv3 130円 (Lv2に対して1.083333倍)
.
.
.
Lv30 400円 (Lv29に対して1.025641倍)

試したこと

**例 ) **の計算結果は下記の式を使いました。
下記でもできますがレベルが数百になったり一度に複数のアイテムを更新する場合フレームに収まらないタイミングが出てきます。それを避ける為にも、初期値から計算する方法を探しております。

C#

1public static long GetPrice(int level, long start, float rate) 2{ 3 if(level > 1) 4 { 5 for (int i = 0; i < level - 1; i++) 6 { 7 start += (long)(start * rate); 8 } 9 } 10 11 return start; 12}
TN8001👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TN8001

2020/06/24 15:36

startPrice * Math.Pow(rate, level - 1); こういうことですか?
IShix

2020/06/28 15:23

ありがとうございます。計算式はそちらで間違いありませんでした。
guest

回答2

0

ベストアンサー

それは[倍率]の[レベル差]乗ですね。
累乗はMath.Powです。
Microsoft Docs
あるいは指数関数Math.Expでも求められます。
もっともこれらはかなり重い処理なので、最初に計算して保持しておいた方がよいかもしれません。

投稿2020/06/24 15:37

ikadzuchi

総合スコア3047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

IShix

2020/06/24 15:49

ありがとうございます。累乗は重いんですね。 Math.PowもMath.Expも使ったことないので勉強してみようと思います。 ご教授いただきありがとうございます!
guest

0

適用すべきレートが極端に多くないのであれば、レート・レベルごとの倍率を関数の初回呼び出し時にキャッシュ変数に記録しておけばいいのではないでしょうか?
2回目以降はキャッシュ変数から適用すべき倍率を取り出してstartに乗算すれば高速に処理できると想います。

投稿2020/06/24 14:44

ku__ra__ge

総合スコア4524

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

IShix

2020/06/24 14:57

なるほど!確かにそうですね。コンストラクタで処理しておけば良いだけなのでかなり簡単にできそうです。 ご教授いただきありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問