2011-01-12 34 views
33

TimeSpan.FromSecondsは2倍の値をとり、100ナノ秒までの値を表すことができますが、この方法では不可能なことに、ミリ秒単位で丸めます。なぜTimeSpan.FromSeconds(double)はミリ秒に丸められますか?

私はこの(文書化された!)動作を正確に突き止めるのに30分を費やしただけで、なぜこのような場合があるのか​​知ることは、無駄な時間を守るのを容易にします。

誰もこの見かけ上反生産的な動作が実装されている理由をお聞かせください。

TimeSpan.FromSeconds(0.12345678).TotalSeconds 
    // 0.123 
TimeSpan.FromTicks((long)(TimeSpan.TicksPerSecond * 0.12345678)).TotalSeconds 
    // 0.1234567 
+0

古い回答が表示されなくて申し訳ありません。 – Peter

+0

「これがなぜこのようなことが起こっているのかが分かり次第、無駄な時間を我慢しやすくなるだろう」と私は思う。それは沈んだコストと考えてください。 – jason

+1

それにも噛まれました。私の理論は、それが.net 1のバグであり、既存のプログラムを壊すので変更されていないということです。 IMO MSは、インテリセンスの記述を更新して、これらの関数がミリ秒の精度しか持たないことを示す必要があります。 – CodesInChaos

答えて

11

自分で見つけたので、これは文書化された機能です。これはdocumentation of TimeSpanで説明しています:

パラメータ

型:System。ダブル

秒数正確なミリ秒単位の精度

これはおそらくダブルが正確ではないためです。倍精度を比較するときには、丸めを行うことをお勧めします。なぜなら、それはあなたが予想していたよりもずっと小さくても小さくてもよいからです。その動作は、ミリ秒単位で入力しようとすると、予期しないナノ秒を実際に提供する可能性があります。私はこれが、ミリ秒単位で値を丸めて小数点を捨てる理由を考えています。

+0

「予想外のナノ秒」は、説得力のある理論のように聞こえます。まだそれは_my_本では正当化されませんが、それはポイントの横にあります。 +1。 –

+0

はい、ほとんどの人にとってはミリ秒で十分でしょう。ナノ秒で作業できるほどスマートな人は 'TimeSpan.FromTicks(TimeSpan.TicksPerSecond * YourSecondsDouble)'を使うことができます。 ;) – GolezTrol

0

FromSeconds :-)いつでもすぐに変更するつもりはないように、それは

public static TimeSpan FromSeconds(double value) 
{ 
    return Interval(value, 0x3e8); 
} 

プライベートメソッド間隔を使用して見えます0x3e8 == 1000

その後、3210そのCONSTに

インターバル方式のマルチプレイ値とlongにキャスト(最後の行を参照)

private static TimeSpan Interval(double value, int scale) 
{ 
    if (double.IsNaN(value)) 
    { 
     throw new ArgumentException(Environment.GetResourceString("Arg_CannotBeNaN")); 
    } 
    double num = value * scale; // Multiply!!!! 
    double num2 = num + ((value >= 0.0) ? 0.5 : -0.5); 
    if ((num2 > 922337203685477) || (num2 < -922337203685477)) 
    { 
     throw new OverflowException(Environment.GetResourceString("Overflow_TimeSpanTooLong")); 
    } 
    return new TimeSpan(((long) num2) * 0x2710L); // Cast to long!!! 
} 

その結果、我々は3(X1000)符号と精度を有しています。 使用投機の権利に関する

+0

私はもちろん見ました。リフレクターは常に_how_には答えることができますが_why_には答えることはできません。これはなぜ**倍増する前にキャストが長く発生するのかを知るのに役立ちましたか?私はそれが文書化されていないバグだと考えています。おそらく、それはまだ修正するよりも文書化が容易なバグでした。要するに、このコードは "なぜ"の質問に答えるものではありません。 –

+1

@romkyns "バグは修正するよりも文書化が容易です!"私はあなたがMicrosoftの新しいスローガンを見つけたと思う! ;-) –

+0

@ニコラス:別の言い回しとして、これは面白いようです。しかし、ここで_unexpected_バグがあるとは思わない。この設計は意図的である可能性があります。 –

7

を調査するための反射鏡..

  1. TimeSpan.MaxValue.TotalMillisecondsが15桁を持つ数を922337203685477.するequatです。
  2. doubleは15桁まで正確です。あなたは(TimeSpan.MaxValueに近くなるようTimeSpanを作成しているとき
  3. TimeSpan.FromSecondsTimeSpan.FromMinutesなどすべてが、そう

(現在は興味深いものではありませんこれは、その後TimeSpanにティックに続い)doubleで表現ミリ秒に変換して行きますまたはMinValue)、変換は正確にミリ秒にのみなります。
は、そこで問題に可能性答えはが「なぜ」:同じ精度にすべての回を持っています。
さらに、最初に値をlongで表されたダンプに変換することによって変換が行われた場合、仕事が改善されたかどうかについて考えることができます。

+0

文書によると、値*が最初にティックに変換されます。 – GolezTrol

+0

@Golez:あなたはそのような文書をどこで見ましたか? [valueパラメータはミリ秒に変換され、ティックに変換され、その数のティックが新しいTimeSpanを初期化するために使用されます。](http://msdn.microsoft.com/en-us/library/system.timespan.fromseconds .aspx) –

+0

すみません、私は間違っています。 – GolezTrol

4

あなたはTimeSpanタイプを設計する開発者であるとします。基本的な機能をすべて備えています。それはすごくうまくいっているようだ。そしてある日、一部のベータテスターに​​沿って来て、あなたにこのコードを示しています

double x = 100000000000000; 
double y = 0.5; 
TimeSpan t1 = TimeSpan.FromMilliseconds(x + y); 
TimeSpan t2 = TimeSpan.FromMilliseconds(x) + TimeSpan.FromMilliseconds(y); 
Console.WriteLine(t1 == t2); 

なぜその出力Falseしていますか?テスターがあなたに尋ねます。これがなぜ起こったのか理解していても(xyの精度の喪失)、と思われます。それから彼はあなたに、このいずれかをスローします。

x = 10.0; 
y = 0.5; 
t1 = TimeSpan.FromMilliseconds(x + y); 
t2 = TimeSpan.FromMilliseconds(x) + TimeSpan.FromMilliseconds(y); 
Console.WriteLine(t1 == t2); 

1つの出力Trueこと!テスターは分かりやすく懐疑的です。

この時点で、あなたは決定を下します。どちらかは、double値から構成されているTimeSpan値間の演算は、その精度doubleタイプ自体 -eg、100000000000000.5(16有効数字)の精度を超える結果を生成するために許可することができ、-OR次のことができ、あなた知って、ではないを許可します。

doubleを使用してTimeSpanを作成する方法では、最も近いミリ秒に丸められるようにします。つまり、はdoubleからTimeSpanへの変換は、doubleからTimeSpanに変換して正確な結果を期待してクライアントがこのような奇妙な振る舞いを見ている場合に私を許してくれます。

私は必ずしもこれがここでの「正しい」決定ではないと主張しているわけではありません。明らかに、このアプローチはそれ自体でいくつかの混乱を引き起こします。私はちょうど決定がある方法か他の方法で作られる必要があったと言っています、そして、これは明らかに決定されたものです。

+0

あなたはこの二倍を完全に禁じるためにこの非常に議論を使うことができます...しかし、私は、この特定のクラスをテストしている間、絶対的な初心者に過度の注意を払っているデザイナーを想像することができます...私たちは、 ) –

関連する問題