2

以下のクラスは音符を表すことになっています。整数のみを使用して、音符の長さ(たとえば、1/2音符、1/4音符、3/8音符など)を保存できるようにしたい。ただし、不規則な長さのノートを扱うまれなケースでは、浮動小数点数を使用して長さを格納できるようにもしたいと思います。

class note{
    string tone;
    int length_numerator;
    int length_denominator;
public:
    set_length(int numerator, int denominator){
        length_numerator=numerator;
        length_denominator=denominator;
    }
    set_length(double d){
        length_numerator=d; // unfortunately truncates everything past decimal point
        length_denominator=1;
    }
}

長さを格納するためにdoubleではなく整数を使用できることが重要である理由は、浮動小数点数の過去の経験では、値が予期せず不正確になることがあるためです。たとえば、16であるはずの数値が、浮動小数点を使用して16.0000000001または15.99999999999(通常は一部の演算に耐えた後)として不思議に格納されることがあります。これにより、同等性のテスト時に問題が発生する可能性があります(16!= 15.99999999999のため)。

変数をintからdouble(値だけでなく変数)に変換することは可能ですか?そうでない場合は、タイプに必要なものに応じて、整数または倍精度浮動小数点数を使用してノートの長さを格納できるようにするために、他に何ができますか?

4

6 に答える 6

4

唯一の問題がfloatの同等性の比較である場合は、floatを使用すると思いますが、最初に「浮動小数点数の比較」/BruceDawsonをお読みください。長くはなく、2つの浮動小数点数を正しく比較する方法を説明しています(絶対差と相対差をチェックすることによって)。

もっと時間があれば、「すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと」を見て、16が16.0000000001または15.99999999999として「不思議に」保存されることがある理由を理解する必要があります。

有理数(または固定小数点演算)に整数を使用する試みは、見た目ほど単純なことはめったにありません。

于 2011-08-11T07:01:27.953 に答える
3

考えられる解決策がいくつかあります。1つ目は、doubleを使用することです。計算を拡張すると不正確な結果が生じる可能性があるのは事実ですが、この場合、除数は通常2の累乗であり、正確な結果が得られます(少なくとも私が見たすべてのマシンで)。異常な値で割ったときに問題が発生するリスクがあるだけです(これは、とにかくdoubleを使用する必要がある場合です)。

また、結果をスケーリングすることもできます。たとえば、ノートを64番目のノートの倍数として表すことができます。これは、ほとんどの値が小さい整数になることを意味します。これは、double(少なくとも通常の表現では)正確であることが保証されています。16であると想定される数値は 、16.000000001または15.99999999として格納されません(ただし、.16であると想定される数値は、.1600000001または.1599999999として格納される可能性があります)。が登場する前はlong long、10進算術クラスdoubleは、52ビットの整数型としてよく使用され、各ステップで実際の値が正確に整数であることを確認していました。(分割のみが問題を引き起こす可能性があります。)

または、有理数を表すある種のクラスを使用することもできます。(たとえば、Boostには1つありますが、他にもあると思います。)これにより、奇妙な値(5番目の音符、誰か?)を正確に保つことができます。また、人間が読める形式の出力にも有利な場合があります。たとえば、分母をテストしてから、「4分音符」などを出力できます。「3/4ノート」のようなものでさえ、「.75ノート」よりもミュージシャンにとって読みやすいでしょう。

于 2011-08-11T07:57:01.787 に答える
2

変数をintからdoubleに変換することはできません。値をintからdoubleに変換することは可能です。どちらを求めているのか完全にはわかりませんが、組合を探しているのかもしれません。

union DoubleOrInt
{
  double d;
  int i;
};

DoubleOrInt length_numerator;
DoubleOrInt length_denominator;

その後、あなたは書くことができます

set_length(int numerator, int denominator){
    length_numerator.i=numerator;
    length_denominator.i=denominator;
}
set_length(double d){
    length_numerator.d=d;
    length_denominator.d=1.0;
}

このアプローチの問題は、現在、ユニオンにintまたはdoubleを格納しているかどうかを絶対に追跡する必要があることです。intを格納してから、doubleとしてアクセスしようとすると、悪いことが起こります。できれば、クラス内でこれを行うことをお勧めします。

于 2011-08-11T07:02:05.443 に答える
0

これは、浮動小数点変数の通常の動作です。これらは常に四捨五入されており、操作によっては最後の桁の値が変わる場合があります。どこかで浮動小数点を読むことをお勧めします(例: http: //floating-point-gui.de/)-特にfp値の比較について。

私は通常、それらを減算し、絶対値を取り、これをイプシロンと比較します。たとえば、if(abs(xy)

于 2011-08-11T07:02:06.953 に答える
0

あなたが持っているとするset_length(double d)と、私の推測では、実際にはダブルが必要だと思います。doubleからintegerの分数への変換は壊れやすく複雑であり、おそらく等式の問題を解決しないことに注意してください(0.24999999は1/4に等しいですか?)。常に分数を使用するか、常に2倍にするかを選択する方がよいでしょう。次に、それらの使用方法を学びます。私が言わなければならないのは、音楽の場合、音符がどのように記述されているかということでさえ、分数​​を持つことは理にかなっています。

于 2011-08-11T07:13:01.387 に答える
0

私の場合は、列挙型を使用します。このシステムを使用すると、何かメモに変換するのも非常に簡単です。これがあなたがそれをすることができる方法です:

class Note {
public:
    enum Type {
        // In this case, 16 represents a whole note, but it could be larger
        // if demisemiquavers were used or something.
        Semiquaver = 1,
        Quaver = 2,
        Crotchet = 4,
        Minim = 8,
        Semibreve = 16
    };


    static float GetNoteLength(const Type &note) 
        { return static_cast<float>(note)/16.0f; }

    static float TieNotes(const Type &note1, const Type &note2)
        { return GetNoteLength(note1)+GetNoteLength(note2); }
};

int main()
{
    // Make a semiquaver
    Note::Type sq = Note::Semiquaver;
    // Make a quaver
    Note::Type q = Note::Quaver;
    // Dot it with the semiquaver from before
    float dottedQuaver = Note::TieNotes(sq, q);

    std::cout << "Semiquaver is equivalent to: " << Note::GetNoteLength(sq) << " beats\n";
    std::cout << "Dotted quaver is equivalent to: " << dottedQuaver << " beats\n";
    return 0;
}

あなたが話すそれらの「不規則な」メモは、を使用して取得することができますTieNotes

于 2011-08-11T07:39:11.747 に答える