9

温度尺度を変換する関数を書いているとしましょう。少なくとも摂氏、華氏、ケルビンをサポートしたいと思います。ソーススケールとターゲットスケールを関数の個別のパラメーターとして渡すか、ある種の組み合わせパラメーターとして渡す方がよいでしょうか。

例1-個別のパラメーター:function convertTemperature( "celsius"、 "fahrenheit"、22)

例2-結合されたパラメーター:function convertTemperature( "cf"、22)

関数内のコードはおそらくそれが重要な場所です。2つのパラメーターを使用すると、使用する式を決定するロジックが少し複雑になりますが、1つのパラメーターがどういうわけか正しく感じられません。

考え?

4

18 に答える 18

15

最初のオプションを選択しますが、リテラル文字列(エラーが発生しやすい)を許可するのではなく、次のように、定数値または言語でサポートされている場合は列挙を取ります。

convertTemperature (TempScale.CELSIUS, TempScale.FAHRENHEIT, 22)
于 2008-09-12T14:21:43.150 に答える
5

言語によって異なります。

通常、列挙型では個別の引数を使用します。

オブジェクト指向言語の場合は、温度クラスをお勧めします。温度は内部に保存され、必要な単位で出力するように機能します。

temp.celsius(); //オブジェクトの温度を摂氏で返します

于 2008-09-12T14:33:28.147 に答える
3

そのようなデザインを書くとき、「ユニットを追加する必要があるとしたら、どのようなデザインが最も簡単にできるのだろうか」と考えたいと思います。これを行うと、次の理由で列挙型が最も簡単であるという結論に達します。

1)新しい値の追加は簡単です。2)文字列比較を避けます

しかし、どのように変換メソッドを記述しますか?3p2は6です。つまり、摂氏、華氏、ケルビンの6つの異なる組み合わせがあります。新しい温帯形式「foo」を追加したい場合はどうなりますか?それは12である4p2を意味します!もう二つ?5p2=20の組み合わせ。あと3つ?6p2 = 30の組み合わせ!

追加の変更ごとに、コードにますます多くの変更が必要になることがすぐにわかります。このため、直接変換は行いません。代わりに、中間変換を行います。ケルビンと言って、私は1つの温度を選びます。そして最初は、ケルビンに変換します。次に、ケルビンを目的の温度に変換します。はい、余分な計算が発生します。ただし、コードのスケーリングが非常に簡単になります。新しい温度単位を追加すると、コードに2つの新しい変更が加えられます。簡単。

于 2008-09-12T14:29:51.070 に答える
2

いくつかのこと:

  • 入力ミスの可能性がある文字列ではなく、構文チェッカーまたはコンパイラーがチェックできる列挙型を使用します。偽性PHPの場合:

    定義('kCelsius'、0); 定義('kFarenheit'、1); 定義('kKelvin'、2); $ a = ConvertTemperature(22、kCelsius、kFarenheit);

また、操作するもの、この場合は変換する温度を最初に配置する方が自然なようです。これにより、パラメーターに論理的な順序が付けられ(convert --what?from?to?)、ニーモニックに役立ちます。

于 2008-09-12T14:25:31.847 に答える
2

最初のアプローチを使用すると、関数ははるかに堅牢になります。別のスケールを追加する必要がある場合は、それを処理するもう1つのパラメーター値です。2番目のアプローチでは、別のスケールを追加するということは、リストにすでにあるスケールの2倍の値を追加することを意味します(たとえば、KをCとFに追加するには、KC、KF、CK、およびを追加する必要があります。 CF.)

プログラムを構造化するための適切な方法は、最初に入力されたものを任意に選択された中間スケールに変換し、次にその中間スケールから出力スケールに変換することです。

より良い方法は、さまざまなスケールの傾きと切片の小さなライブラリを用意し、入力スケールと出力スケールの数値を調べて、1つの一般的なステップで計算を行うことです。

于 2008-09-12T14:30:44.330 に答える
2

C# (およびおそらく Java) では、温度を摂氏 (または何でも) としてプライベートに格納し、get および set ステートメントですべての変換を行う摂氏、華氏、およびケルビンのプロパティを持つ Temperature クラスを作成するのが最善でしょう?

于 2008-09-12T15:00:59.983 に答える
1

@Rob@wcmと@Davidが説明したのと同じように...

public class Temperature
{
    private double celcius;

    public static Temperature FromFarenheit(double farenheit)
    {
        return new Temperature { Farhenheit = farenheit };
    }

    public static Temperature FromCelcius(double celcius)
    {
        return new Temperature { Celcius = celcius };
    }

    public static Temperature FromKelvin(double kelvin)
    {
        return new Temperature { Kelvin = kelvin };
    }

    private double kelvinToCelcius(double kelvin)
    {
        return 1; // insert formula here
    }

    private double celciusToKelvin(double celcius)
    {
        return 1; // insert formula here
    }

    private double farhenheitToCelcius(double farhenheit)
    {
        return 1; // insert formula here
    }

    private double celciusToFarenheit(double kelvin)
    {
        return 1; // insert formula here
    }

    public double Kelvin
    {
        get { return celciusToKelvin(celcius); }
        set { celcius = kelvinToCelcius(value); }
    }

    public double Celcius
    {
        get { return celcius; }
        set { celcius = value; }
    }

    public double Farhenheit
    {
        get { return celciusToFarenheit(celcius); }
        set { celcius = farhenheitToCelcius(value); }
    }
}
于 2008-09-12T15:23:55.530 に答える
1

変換の数によって異なります。列挙型として指定された1つのパラメーターを選択する可能性があります。この拡張バージョンの変換について考えてみます。

enum Conversion
{
  CelsiusToFahrenheit,
  FahrenheitToCelsius,
  KilosToPounds
}

Convert(Conversion conversion, X from);

これで、呼び出しの時点で正しい型の安全性が得られました。正しく型指定されたパラメーターを指定すると、実行時の結果が正しくなくなります。代替案を検討してください。

enum Units
{
  Pounds,
  Kilos,
  Celcius,
  Farenheight
}

Convert(Unit from, Unit to, X fromAmount);

安全に電話できます

Convert(Pounds, Celcius, 5, 10);

しかし、結果は無意味であり、実行時に失敗する必要があります。はい、私はあなたが現時点で温度だけを扱っていることを知っています、しかし一般的な概念はまだ成り立ちます(私は信じます)。

于 2008-09-12T14:24:30.257 に答える
1

温度タイプから列挙を作成し、2つのスケールパラメーターを渡します。(c#で)のようなもの:


public void ConvertTemperature(TemperatureTypeEnum SourceTemp,
                               TemperatureTypeEnum TargetTemp, 
                               decimal Temperature)
{}

于 2008-09-12T14:24:52.020 に答える
1

私が選ぶだろう

例1-個別のパラメーター:function convertTemperature( "celsius"、 "fahrenheit"、22)

そうしないと、関数定義内で「cf」を「celsius」と「fahrenheit」に解析して、必要な変換スケールを取得する必要があり、混乱する可能性があります。

Googleの検索ボックスのようなものをユーザーに提供している場合、「cf」のような便利なショートカットがあると便利です。ただし、その下では、上記のようにconvertTemperature()を呼び出す前に、外部関数で「cf」を「celsius」と「fahrenheit」に変換します。

于 2008-09-12T14:25:57.227 に答える
1

この場合、単一のパラメーターは完全にあいまいに見えます。

関数は、温度あるスケールから別のスケールに変換します。
IMOソーススケールとターゲットスケールを別々のパラメーターとして渡す方が自然です。私は絶対に最初の議論の形式を把握しようとはしません。

于 2008-09-12T14:27:23.167 に答える
1

これに対する私の見解は次のとおりです(PHPを使用):

function Temperature($value, $input, $output)
{
    $value = floatval($value);

    if (isset($input, $output) === true)
    {
        switch ($input)
        {
            case 'K': $value = $value - 273.15; break; // Kelvin
            case 'F': $value = ($value - 32) * (5 / 9); break; // Fahrenheit
            case 'R': $value = ($value - 491.67) * (5 / 9); break; // Rankine
        }

        switch ($output)
        {
            case 'K': $value = $value + 273.15; break; // Kelvin
            case 'F': $value = $value * (9 / 5) + 32; break; // Fahrenheit
            case 'R': $value = ($value + 273.15) * (9 / 5); break; // Rankine
        }
    }

    return $value;
}

基本的に、$input値は標準の摂氏スケールに変換されてから、再びスケールに変換されます$output。1 つの関数ですべてを制御します。=)

于 2010-12-15T15:27:32.733 に答える
1

オブジェクトを使用してプログラミングの問題を解決する方法を常に探しています。これが、関数を使って問題を解決するだけだったときよりもオブジェクト指向になっていることを意味することを願っていますが、それはまだわかりません。

C# の場合:

interface ITemperature
{
     CelciusTemperature ToCelcius();
     FarenheitTemperature ToFarenheit();
}

struct FarenheitTemperature : ITemperature
{
    public readonly int Value;
    public FarenheitTemperature(int value)
    {
        this.Value = value;
    }

    public FarenheitTemperature ToFarenheit() { return this; }
    public CelciusTemperature ToCelcius()
    {
        return new CelciusTemperature((this.Value - 32) * 5 / 9);
    }

}

struct CelciusTemperature
{
    public readonly int Value;
    public CelciusTemperature(int value)
    {
        this.Value = value;
    }

    public CelciusTemperature ToCelcius() { return this; }
    public FarenheitTemperature ToFarenheit()
    {
        return new FarenheitTemperature(this.Value * 9 / 5 + 32);
    }
}

そしていくつかのテスト:

        // Freezing
        Debug.Assert(new FarenheitTemperature(32).ToCelcius().Equals(new CelciusTemperature(0)));
        Debug.Assert(new CelciusTemperature(0).ToFarenheit().Equals(new FarenheitTemperature(32)));

        // crossover
        Debug.Assert(new FarenheitTemperature(-40).ToCelcius().Equals(new CelciusTemperature(-40)));
        Debug.Assert(new CelciusTemperature(-40).ToFarenheit().Equals(new FarenheitTemperature(-40)));

このアプローチで回避できるバグの例:

        CelciusTemperature theOutbackInAMidnightOilSong = new CelciusTemperature(45);
        FarenheitTemperature x = theOutbackInAMidnightOilSong; // ERROR: Cannot implicitly convert type 'CelciusTemperature' to 'FarenheitTemperature'

ケルビン変換の追加は演習として残します。

于 2008-09-12T14:49:34.923 に答える
1

ところで、質問文で示唆されているように、3 つのパラメーターのバージョンを実装するために、より多くの作業を行う必要はありません。

これらはすべて線形関数なので、次のようなものを実装できます

float LinearConvert(float in, float scale, float add, bool invert);

最後の bool は、順変換を行うか逆変換を行うかを示します。

変換手法内で、X -> ケルビンのスケール/追加ペアを使用できます。形式 X を Y に変換する要求を受け取った場合、最初に X -> ケルビンを実行し、次に Y -> ケルビン プロセスを逆にして (最後の bool を LinearConvert に反転することによって) ケルビン -> Y を実行できます。

この手法により、convert 関数で 4 行の実際のコードと、変換する必要がある型ごとに 1 つのデータが得られます。

于 2008-09-12T15:07:18.283 に答える
1

私はどちらかの方向に完全に独り占めすると思います。単位のような変換を行うミニ言語を書くことができます:

$ units 'tempF(-40)' tempC
    -40

または、最近のConvert::Temperature Perl モジュールが行うように、個々の関数を使用します。

use Convert::Temperature;

my $c = new Convert::Temperature();

my $res = $c->from_fahr_to_cel('59');

しかし、ここで重要なポイントがあります。あなたが使用している言語には、すでに変換機能がありますか? もしそうなら、彼らはどのコーディング規約を使用していますか? そのため、言語が C の場合は、atoi および strtod ライブラリ関数 (未テスト) の例に従うのが最善です。

double fahrtocel(double tempF){
    return ((tempF-32)*(5/9));
}

double celtofahr(double tempC){
    return ((9/5)*tempC + 32);
}

この投稿を書いているときに、emacs を使用した日付の変換に関する非常に興味深い投稿に出くわしました。このトピックの要点は、変換ごとに 1 つの関数スタイルを使用していることです。また、変換は非常にあいまいになる可能性があります。SQL を使用して日付計算を行う傾向があるのは、そのコードに多くのバグがある可能性が低いためです。今後は、emacs の使用を検討する予定です。

于 2008-09-12T17:09:49.580 に答える
0

私の投票は、変換タイプの2つのパラメーターであり、1つは値(最初の例のように)です。ただし、文字列リテラルの代わりに列挙型を使用します。

于 2008-09-12T14:22:36.813 に答える
0

単位の仕様については、言語で許可されている場合は列挙型を使用してください。

内部のコードは2つで簡単になると思います。pre-add、multiplty、post-addのテーブルがあり、一方のユニットのアイテムに値を実行し、次にもう一方のユニットのアイテムに逆に値を実行します。基本的に、入力温度を内部の共通ベース値に変換してから、他のユニットに変換します。この関数全体はテーブル駆動型になります。

于 2008-09-12T14:23:14.317 に答える
0

複数の回答を受け入れる方法があればいいのにと思います。みんなの推奨に基づいて、複数のパラメーターを使い続け、文字列を列挙型/定数に変更し、変換する値をパラメーター リストの最初の位置に移動すると思います。関数内では、共通の中間点として Kelvin を使用します。

以前は、変換ごとに個別の関数を作成していましたが、convertTemperature() 関数全体は、switch ステートメントをネストしたラッパーにすぎませんでした。私は従来の ASP と PHP の両方で書いていますが、どの言語でも質問できるようにしたかったのです。

于 2008-09-13T01:33:08.280 に答える