4

我有一个 C# 应用程序,我需要在 3 个不同的单位之间进行转换(例如:升、加仑和品脱)。

该应用程序需要了解特定体积的液体,例如:1 品脱、10 品脱、20 品脱和 100 品脱。我打算进行计算并对值进行硬编码(不理想但必要),

我正在寻找一种数据结构,它可以让我轻松地从一个单位转换为另一个单位。

有什么建议么?

请注意:我实际上并没有使用大量的液体,它只是一个例子!

4

5 回答 5

8

您可以存储转换因子矩阵,其中

  • a: 是升
  • b:是品脱
  • c: 加仑

你有(不准确,但假设一升有两品脱,一加仑有 4 升)

   a     b       c
a  1     2     0.25
b  0.5   1     0.125
c  4     8       1

或者,您可以决定在转换为另一种类型之前将所有内容转换为基值(升),然后您只需要第一行。

将其包装在一个方法中,该方法采用多个单位和“from”类型和“two”类型进行转换。

希望这可以帮助

编辑:一些代码,根据要求

    public enum VolumeType
    {
        Litre = 0,
        Pint = 1,
        Gallon = 2
    }

    public static double ConvertUnits(int units, VolumeType from, VolumeType to)
    {
        double[][] factor = 
            {
                new double[] {1, 2, 0.25},
                new double[] {0.5, 1, 0.125},
                new double[] {4, 8, 1}
            };
        return units * factor[(int)from][(int)to];
    }

    public static void ShowConversion(int oldUnits, VolumeType from, VolumeType to)
    {
        double newUnits = ConvertUnits(oldUnits, from, to);
        Console.WriteLine("{0} {1} = {2} {3}", oldUnits, from.ToString(), newUnits, to.ToString());
    }


    static void Main(string[] args)
    {
        ShowConversion(1, VolumeType.Litre, VolumeType.Litre);  // = 1
        ShowConversion(1, VolumeType.Litre, VolumeType.Pint);   // = 2
        ShowConversion(1, VolumeType.Litre, VolumeType.Gallon); // = 4
        ShowConversion(1, VolumeType.Pint, VolumeType.Pint);    // = 1
        ShowConversion(1, VolumeType.Pint, VolumeType.Litre);   // = 0.5
        ShowConversion(1, VolumeType.Pint, VolumeType.Gallon);  // = 0.125
        ShowConversion(1, VolumeType.Gallon, VolumeType.Gallon);// = 1
        ShowConversion(1, VolumeType.Gallon, VolumeType.Pint);  // = 8
        ShowConversion(1, VolumeType.Gallon, VolumeType.Litre); // = 4
        ShowConversion(10, VolumeType.Litre, VolumeType.Pint);  // = 20
        ShowConversion(20, VolumeType.Gallon, VolumeType.Pint); // = 160
    }
于 2009-01-30T10:55:14.737 回答
5

我通过提供正确的访问方法(属性)以另一种语言完成了这项工作:

for the class Volume:
  AsLitre
  AsGallon
  AsPint

for the class Distance:
  AsInch
  AsMeter
  AsYard
  AsMile

另一个优点是内部格式无关紧要。

于 2009-01-30T10:53:27.597 回答
2

请看一下Explicit Interface Implementation,我认为它可以帮助你,示例是关于你需要的。

编辑:从 MSDN 复制的示例

interface IEnglishDimensions 
{
   float Length();
   float Width();
}
// Declare the metric units interface:
interface IMetricDimensions 
{
   float Length();
   float Width();
}
// Declare the "Box" class that implements the two interfaces:
// IEnglishDimensions and IMetricDimensions:
class Box : IEnglishDimensions, IMetricDimensions 
{
   float lengthInches;
   float widthInches;
   public Box(float length, float width) 
   {
      lengthInches = length;
      widthInches = width;
   }
// Explicitly implement the members of IEnglishDimensions:
   float IEnglishDimensions.Length() 
   {
      return lengthInches;
   }
   float IEnglishDimensions.Width() 
   {
      return widthInches;      
   }
// Explicitly implement the members of IMetricDimensions:
   float IMetricDimensions.Length() 
   {
      return lengthInches * 2.54f;
   }
   float IMetricDimensions.Width() 
   {
      return widthInches * 2.54f;
   }
   public static void Main() 
   {
      // Declare a class instance "myBox":
      Box myBox = new Box(30.0f, 20.0f);
      // Declare an instance of the English units interface:
      IEnglishDimensions eDimensions = (IEnglishDimensions) myBox;
      // Declare an instance of the metric units interface:
      IMetricDimensions mDimensions = (IMetricDimensions) myBox;
      // Print dimensions in English units:
      System.Console.WriteLine("Length(in): {0}", eDimensions.Length());
      System.Console.WriteLine("Width (in): {0}", eDimensions.Width());
      // Print dimensions in metric units:
      System.Console.WriteLine("Length(cm): {0}", mDimensions.Length());
      System.Console.WriteLine("Width (cm): {0}", mDimensions.Width());
   }
}
于 2009-01-30T10:49:21.597 回答
1

In case it is helpfull, you might want to use a nuget package that's doing conversions between various units:

UnitConversion on:

Full disclosure: I'm currently maintaining this package.

于 2018-02-10T15:24:16.697 回答
0

这是完整的源代码:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

namespace UnitConversion
{
    internal delegate double Converter(double value);

    class UnitConverter
    {
        private readonly IDictionary<string, IDictionary<string, Converter>> converters =
            new Dictionary<string, IDictionary<string, Converter>>();
        private readonly NumberFormatInfo numberFormatInfo;

        public UnitConverter()
        {
            numberFormatInfo = (NumberFormatInfo)NumberFormatInfo.InvariantInfo.Clone();
            numberFormatInfo.NumberDecimalSeparator = ".";
            numberFormatInfo.NumberGroupSeparator = String.Empty;
        }

        public void ParseConverterDefinition(string converterDefinition)
        {
            string[] parts = converterDefinition.Split(' ');
            double sourceUnitsValue = double.Parse(parts[0], NumberFormatInfo.InvariantInfo);
            double targetUnitsValue = double.Parse(parts[3], NumberFormatInfo.InvariantInfo);

            AddConverters(parts[1], sourceUnitsValue, parts[4], targetUnitsValue);
            AddConverters(parts[4], targetUnitsValue, parts[1], sourceUnitsValue);
        }

        private void AddConverters(string sourceUnits, double sourceUnitsValue, string targetUnits, double targetUnitsValue)
        {
            if (!converters.ContainsKey(sourceUnits))
                converters.Add(sourceUnits, new Dictionary<string, Converter>());

            converters[sourceUnits][targetUnits] =
                delegate(double value)
                { return value * targetUnitsValue / sourceUnitsValue; };
        }

        public double? Convert(double value, string sourceUnits, string targetUnits, params string[] skipUnits)
        {
            if (!converters.ContainsKey(sourceUnits))
                return null;

            if (converters[sourceUnits].ContainsKey(targetUnits))
                return converters[sourceUnits][targetUnits](value);

            foreach (KeyValuePair<string, Converter> pair in converters[sourceUnits])
            {
                if (Array.IndexOf(skipUnits, pair.Key) != -1)
                    continue;

                List<string> skip = new List<string>(skipUnits);
                skip.Add(sourceUnits);

                double? result = Convert(converters[sourceUnits][pair.Key](value), pair.Key, targetUnits, skip.ToArray());
                if (result != null)
                    return result;
            } // foreach

            return null;
        }

        public string Convert(string conversionRequest)
        {
            string[] parts = conversionRequest.Split(' ');
            return ConvertFormatted(double.Parse(parts[0], NumberFormatInfo.InvariantInfo), parts[1], parts[4]);
        }

        public string ConvertFormatted(double value, string sourceUnits, string targetUnits)
        {
            double? convertedValue = Convert(value, sourceUnits, targetUnits);
            if (convertedValue == null)
                return "No conversion is possible.";

            return string.Format("{0} {1} = {2} {3}", value.ToString("N6", numberFormatInfo), sourceUnits,
                convertedValue < 0.01 || convertedValue > 1000000 ?
                    convertedValue.Value.ToString("#.######e+00", numberFormatInfo) :
                    convertedValue.Value.ToString("N6", numberFormatInfo),
                targetUnits);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            UnitConverter unitConverter = new UnitConverter();

            foreach (string s in File.ReadAllLines("Conversions.txt"))
            {
                if (s.IndexOf("?") == -1)
                    unitConverter.ParseConverterDefinition(s);
                else
                    Console.WriteLine(unitConverter.Convert(s));
            } // foreach
        }
    }
}

它以以下格式处理文件

7200.0 second = 2 hour
10.0 glob = 1 decaglob
1 day = 24.0 hour
1 minute = 60 second
1 glob = 10 centiglob
1 day = 24 hour
1 year = 365.25 day
50 centiglob = ? decaglob
5.6 second = ? hour
3 millisecond = ? hour
5.6 second = ? day
1 day = ? glob
1 hour = ? second
1 year = ? second

并计算例如 50 centiglobs in decaglobs。

此代码能够进行链式转换(例如年 -> 日 -> 小时 -> 秒)。

于 2009-01-30T10:55:52.020 回答