2010-12-03 10 views
14

C#では、浮動小数点数を返す「Math.Cos」関数がないということを私はバグします。あなたが戻すことができる唯一の値はdoubleなので、floatにキャストする必要があります。 ので、同じように:
float val = (float)Math.Cos(someVal);"System.Math.Cos"がa(float)を返すことはできますか?

私は私が厳密にフロートを使用してDirect3Dの中のものをやっているので、浮動小数点数を使用する必要があります。 フロートは32ビットであるため、グラフィックスの世界では(これは現在のように)はるかに一般的です。

C#で使用できる機能はありますか?単にC++のような浮動小数点を処理するだけのものですか?

これはXNA & Linux for OpenGLで実行する必要があるため、C++のものはすべてラップしたくありません。

:doubleをfloatにキャストしていないコードを使用するとよいでしょう。

+3

あなたが過負荷になる可能性がありあなた自身のバージョンでmath.cos()をキャストするだけです。 – Puppy

+1

Direct3Dでは浮動小数点数が必要ですが、ほとんどの(ただしすべてではありません)丸めエラーの問題を回避するため、変換するまではdoubleを使用する方が良いです。 – ChrisF

+4

@ChrisF - これは本当にゲームでは真実ではありません。丸めはめったに問題にならないか、クランプで対処することができます.Doubleを避けることで大幅な節約が実現します。 – codekaizen

答えて

6

詳細な数値計算に入ることなく、正確な Cos関数を記述することはできません。ここでは拡張メソッドを使用して、しかし提案です:

class Program 
{ 
    static void Main(string[] args) 
    { 
     float cos = Math.Cos(.25d).ToFloat(); 

     Console.WriteLine("cos(.25d) = {0}", cos); 

     Console.ReadKey(); 
    } 
} 

public static class MathExtensions 
{ 
    public static float ToFloat(this double value) 
    { 
     return (float)value; 
    } 
} 

これはFunc<T, TResult>を使用して、独自のMathF静的クラスを作成する別の方法です:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("cos(.25d) = {0}", MathF.Cos(.25d)); 
     Console.WriteLine("sin(.25d) = {0}", MathF.Sin(.25d)); 

     Console.ReadKey(); 
    } 
} 

public static class MathF 
{ 
    public static Func<double, float> Cos = angleR => (float)Math.Cos(angleR); 
    public static Func<double, float> Sin = angleR => (float)Math.Sin(angleR); 
} 

他の人が指摘したように、のFuncデリゲートをとして遅くなります彼のテストコードで確認されたzezba(私は、代議員がずっと遅くなることを知らなかった)。最も速いのは、フロートするための直接キャストです。中盤は、MathF静的クラスの単純な静的メソッド呼び出しです。

+2

Cos()は単精度変換拡張機能には適していません。 – Jimmy

+0

@Jimmy:edited ... 'ToFloat()' – IAbstract

+5

なぜstatic float Cos(double angleR){...の代わりに 'static Func Cos = angleR => ...'を書くのですか? } '? – Juliet

4

頻繁に使用されるすべての戻り値型をdouble型の浮動小数点数に変換するメソッドを使用してMathCommonMethodsクラスを作成します。これにより、長期的な入力を省くことができます。

フロートとして値を返す既存の関数がある限り、私はそれを聞いていません。

アプリケーションにとって精度が重要な場合は、精度を落とさないようにキャストするときにも注意する必要があります。

+4

"オーバーロード"は、1つのクラスに同じ名前のメソッドのグループを定義することを意味します。別のクラスにメソッドを追加することについて話しているなら、それはオーバーロードではありません。それは単にメソッドを定義することです。 –

+0

私は派生したクラスを意味していましたが、依然としてオーバーロードと見なされています。良いキャッチしかし、私の最初の答えは明らかではなかった。 –

+2

'System.Math'は静的クラスです。あなたはそれから派生することはできません。 –

2

キャストを避けたい場合は、別の実装が必要です。クロスプラットフォームを実行している場合は、プラットフォームに基づいてさまざまな実装を行うことができるプラットフォーム抽象レイヤーを作成できます。これはパフォーマンスに役立ちます。 perfが問題ではない場合(これはこれまでのゲームの場合です)、ユーティリティ関数を作成してキャストを実行することは良い解決策です。

+0

私はそれについて考えていた、それは良い考えです。しかし、私は物事を複雑にしたくない。私はそれを試して、私がそれからどんなスピードの改善を見ているかを見てもいいと思うが。 PC、Mac、Linuxではいいですが、XBOXやPhone7のXNAでは動作しません。 – zezba9000

3

私はいくつかのベンチマークを実行して、どの方法が「dboarman」の返信を読み込んだ後で最も速かったかを確認しました。悲しいことに、厳密にC#&を使ってキャスティングすることなくそれを行う方法はありません。最も速い方法はちょうど現場でキャストすることです。

これらのテストは、以下の仕様を使用してコンパイルされた::

C# .NET 4.0 
ConsoleApplication - Release - Optimized code - x64 
4gb ram, 2.4ghz AMD_X2_DualCore 4600 CPU, running Windows7 Ultimate. 

コード:

static void Main(string[] args) 
{ 
    //Start 
    Console.Write("Hit Enter to Start\n"); 
    Console.ReadLine(); 
    long num = 100; 
    long mil = 0; 
    float val = 0.01f; 
    Stopwatch startTime = new Stopwatch(); 

    //Run 
    for(long i = 0; i != num; ++i) 
    { 
     startTime.Restart(); 
     for(uint i2 = 0; i2 != 1000000; ++i2) val = (float)System.Math.Cos(val);// 48 Milliseconds 
     //for(uint i2 = 0; i2 != 1000000; ++i2) val = System.Math.Cos(val).ToFloat();// 53 Milliseconds 
     //for(uint i2 = 0; i2 != 1000000; ++i2) val = MathF2.Cos(val);// 59 Milliseconds 
     //for(uint i2 = 0; i2 != 1000000; ++i2) val = MathF.Cos(val);// 63 Milliseconds 
     startTime.Stop(); 
     mil += startTime.ElapsedMilliseconds; 
    } 

    //End 
    mil /= num; 

    //Print 
    Console.Write("Milliseconds = "+mil.ToString()); 
    Console.ReadLine(); 
} 

ここでは、テストのための基本数学のコードである::

public static class MathF 
{ 
    public static Func<double, float> Cos = angleR => (float)System.Math.Cos(angleR); 
    public static Func<double, float> Sin = angleR => (float)System.Math.Sin(angleR); 
} 

public static class MathF2 
{ 
    public static float Cos(float pValue) {return (float)System.Math.Cos(pValue);} 
} 

public static class MathExtensions 
{ 
    public static float ToFloat(this double value) 
    { 
     return (float)value; 
    } 
} 
+0

私はあなたのテストコードを正しく読んだら、標準キャストメソッドで100万のキャストを完了するための時間は48msですか?テストでいい仕事。正直なところ、Funcデリゲートがどれほど遅いか分からなかった。 – IAbstract

+0

はい、あなたは正しいです、400万回で100万のキャストが完了します。私は100回テストを繰り返し、平均を得て結果をプリントします。 – zezba9000

関連する問題