我有一个C#应用程序,我需要在3个不同的单位之间进行转换(例如:升,加仑和品脱)。
应用程序需要知道某些体积的液体,比如:1品脱,10品脱,20品脱和100品脱。我打算进行计算并对值进行硬编码(不理想但必要),
我正在寻找一种数据结构,可以让我轻松地从一个单位转换为另一个单位。
有什么建议吗?
请注意:我不是实际使用大量液体,这只是一个例子!
答案 0 :(得分:7)
您可以存储转换因子矩阵
你有(不准确,但假设有一品脱到一升和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
}
答案 1 :(得分:5)
我通过提供正确的访问方法(属性)以其他语言完成此操作:
for the class Volume:
AsLitre
AsGallon
AsPint
for the class Distance:
AsInch
AsMeter
AsYard
AsMile
另一个优点是内部格式无关紧要。
答案 2 :(得分: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());
}
}
答案 3 :(得分:1)
答案 4 :(得分: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
例如,计算出decaglobs中的50个centiglobs。
此代码能够进行链式转换(例如年 - >天 - >小时 - >秒>。