编写转换函数的最佳方法

时间:2008-09-12 14:19:30

标签: coding-style

假设我正在编写一个在温度范围之间进行转换的函数。我想至少支持Celsius,Fahrenheit和Kelvin。是否更好地将源比例和目标比例作为函数的单独参数或某种组合参数传递?

示例1 - 单独的参数: function convertTemperature(“celsius”,“fahrenheit”,22)

示例2 - 组合参数: function convertTemperature(“c-f”,22)

函数内部的代码可能在其中。使用两个参数,确定我们将要使用的公式的逻辑稍微复杂一些,但单个参数在某种程度上感觉不正确。

思想?

18 个答案:

答案 0 :(得分:15)

使用第一个选项,但不是允许文字字符串(容易出错),如果您的语言支持,则采用常量值或枚举,如下所示:

convertTemperature (TempScale.CELSIUS, TempScale.FAHRENHEIT, 22)

答案 1 :(得分:5)

取决于语言。

通常,我会在枚举中使用单独的参数。

如果它是一种面向对象的语言,那么我建议使用温度等级,温度存储在内部然后你喜欢,然后用它来输出它所需要的任何单位:

temp.celsius(); //以摄氏度返回对象临时温度

答案 2 :(得分:3)

在编写这样的设计时,我喜欢自己想一想,“如果我需要增加一个额外的单元,那么设计什么才能让它最简单呢?”这样做,我得出结论,由于以下原因,枚举最容易:

1)添加新值很容易。 2)我避免进行字符串比较

但是,您如何编写转换方法? 3p2是6.这意味着有6种不同的摄氏度,华氏度和开尔文组合。如果我想添加一个新的温和格式“foo”怎么办?这意味着4p2即12!还有两个? 5p2 = 20组合。还有三个? 6p2 = 30种组合!

您可以快速了解每个其他修改如何需要对代码进行越来越多的更改。因此我不做直接转换!相反,我做了一个中间转换。凯尔文说,我会选择一个温度。最初,我会转换为开尔文。然后我将开尔文转换为所需的温度。是的,它会导致额外的计算。但是,它使得代码更容易被打乱。添加新的温度单位将始终只对代码进行两次新的修改。容易。

答案 3 :(得分:2)

一些事情:

  • 我使用语法检查器或编译器可以检查的枚举类型,而不是可能输入错误的字符串。在Pseudo-PHP中:

    define('kCelsius',0); define('kFarenheit',1); define('kKelvin',2); $ a = ConvertTemperature(22,kCelsius,kFarenheit);

此外,对我来说放置你操作的东西似乎更自然,在这种情况下要转换的温度,首先。它为您的参数提供了逻辑排序(转换 - 从?到?),从而有助于助记符。

答案 4 :(得分:2)

在C#(和probaly Java)中,最好创建一个温度类,私密地存储温度,如Celcius(或其他),并且具有Celcius,Fahrenheit和Kelvin属性,可以在他们的获取中为您完成所有转换。设定报表?

答案 5 :(得分:2)

如果您使用第一种方法,您的功能将更加强大。如果您需要添加另一个比例,那么还需要处理一个参数值。在第二种方法中,添加另一个比例意味着添加与列表中已有比例一样多的值,时间为2.(例如,要将K添加到C和F,您必须添加KC,KF,CK和CF)

构建程序的一个不错的方法是首先将任何内容转换为任意选择的中间标度,然后从该中间标度转换为输出标度。

更好的方法是为各种比例设置一个小的斜坡和截距库,只需查看输入和输出比例的数字,然后在一个通用步骤中进行计算。

答案 6 :(得分: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比例 - 一个函数来统治它们。 =)

答案 7 :(得分: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转换日期的very interesting post。这个主题的内容是它使用了每个转换函数的一种风格。此外,转换可能非常模糊。我倾向于使用SQL进行日期计算,因为该代码中似乎不太可能存在许多错误。将来,我将考虑使用emacs。

答案 8 :(得分: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); }
    }
}

答案 9 :(得分:1)

顺便说一下,如问题陈述所示,实现三参数版本不需要做更多的工作。

这些都是线性函数,因此您可以实现类似

的功能
float LinearConvert(float in, float scale, float add, bool invert);

最后一个bool表示你是想进行正向变换还是反向变换。

在您的转换技术中,您可以为X创建缩放/添加对 - >开尔文。当您收到将格式X转换为Y的请求时,您可以先运行X - > Kelvin,然后是Kelvin - > Y通过反转Y - >开尔文过程(通过将最后一个bool翻转到LinearConvert)。

这种技术在转换函数中为您提供了4行真实代码,并为您需要转换的每种类型提供了一条数据。

答案 10 :(得分:1)

我一直在寻找使用对象来解决编程问题的方法。我希望这意味着我比仅仅使用函数解决问题时更加OO,但这还有待观察。

在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'

添加开尔文转换是一项练习。

答案 11 :(得分:1)

在这种情况下,单个参数看起来完全模糊不清;

功能将温度一个刻度转换为另一个刻度
IMO将源和目标比例作为单独的参数传递更为自然。我绝对不想尝试掌握第一个论点的格式。

答案 12 :(得分:1)

我会选择

  

示例1 - 单独的参数:function convertTemperature(“celsius”,“fahrenheit”,22)

否则,在您的函数定义中,您必须将“c-f”解析为“celsius”和“fahrenheit”,以获得所需的转换比例,这可能会变得混乱。

如果您向用户提供Google搜索框之类的内容,那么拥有像“c-f”这样便捷的快捷方式对他们来说很不错。但是,在下面,我会在调用convertTemperature()之前将外部函数中的“c-f”转换为“cels”和“fahrenheit”。

答案 13 :(得分:1)

我会从温度类型中进行枚举并传入2个比例参数。像(在c#中)的东西:


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

答案 14 :(得分: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);

但结果毫无意义,你必须在运行时失败。是的,我知道你现在只处理温度,但一般概念仍然存在(我相信)。

答案 15 :(得分:0)

如果您的语言允许,请使用枚举,以获取单位规格。

我会说两个内部的代码会更容易。我有一个带有pre-add,multiplty和post-add的表,并通过一个单元的项目运行值,然后通过另一个单元的项目反向运行。基本上将输入温度转换为内部的公共基值,然后输出到另一个单元。整个函数将由表驱动。

答案 16 :(得分:0)

我希望有一些方法可以接受多个答案。根据每个人的建议,我想我会坚持使用多个参数,将字符串更改为枚举/常量,并将值转换为参数列表中的第一个位置。在函数内部,我将使用开尔文作为共同的中间地带。

以前我为每次转换编写了单独的函数,整个convertTemperature()函数只是一个包含嵌套switch语句的包装器。我用经典的ASP和PHP编写,但我想把问题留给任何语言。

答案 17 :(得分:0)

我的投票是转换类型的两个参数,一个用于值(如第一个示例中所示)。但是,我会使用枚举而不是字符串文字。