单位换算程序

发布于 2024-08-17 04:42:59 字数 226 浏览 7 评论 0原文

我正在为我的学期项目开发一个单位转换器。我需要有关类/接口/抽象类的结构的一些帮助。我想要一些可以由类(DegreesConverter、MassConverter、LenghtConverter)继承的接口或抽象类。就像接口 IUnitConvert 一样。首先,我将处理角度(度、弧度、梯度)、力(牛顿、帕斯卡)和数据(字节、千字节、兆字节、千兆字节、太字节)的单位。有什么建议吗?

I am developing a unit converter for my semester project. I need some help on the structure of the classes/interfaces/abstract classes. I want some interface or abstract class that can be inherited by classes (DegreesConverter, MassConverter, LenghtConverter). Like maybe interface IUnitConvert<Type>. I will be dealing with units of angles (degrees, radians, gradians), force (newtons, pascals) and data (byte, kilobyte, megabyte, gigabyte, terabyte) for starters. Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

偏爱自由 2024-08-24 04:42:59

首先想到的是像 System.TimeSpan 这样的东西,其中同一个类代表时间,并且您可以通过属性以不同的单位访问它。

您可以将值内部存储在某个常量单位(大概是 SI)中,并在属性 getter / setter 中进行转换:

Distance d = new Distance;
d.Meters = 5000;
var km = d.Kilometers; // km = 5;

或者您可以为每个单位创建类:

public sealed class DistanceUnit
{
    public DistanceUnit(string name, string symbol, double scale)
    {
        Name = name;
        Symbol = symbol;
        Scale = scale;
    }

    public string Name { get; private set; }
    public string Symbol { get; private set; }
    public double Scale { get; private set; }
}


public abstract class Distance
{
    protected Distance(double value)
    {
        this.Value = value;
    }

    protected Distance()
    {
    }

    public double Value { get; set; }

    public abstract DistanceUnit Unit { get; }

    public override string ToString()
    {
        return this.Value + " " + Unit.Symbol;
    }


    public static void Convert<TIn, TOut>(TIn original, out TOut result)
        where TIn : Distance, new()
        where TOut : Distance, new()
    {

        result = new TOut();

        var scale = result.Unit.Scale / original.Unit.Scale;

        result.Value = original.Value * scale;
    }

}

public sealed class Meter : Distance
{

    private static readonly DistanceUnit s_Unit = new DistanceUnit("Meter", "m", 1);

    public Meter(double value) : base(value)
    {
    }

    public Meter()
    {
    }

    public override DistanceUnit Unit
    {
        get { return s_Unit; }

    }
}

public sealed class Kilometer : Distance
{
    private static readonly DistanceUnit s_Unit = new DistanceUnit("Kilometer", "km", .001);

    public Kilometer()
    {
    }

    public Kilometer(double value)
        : base(value)
    {
    }

    public override DistanceUnit Unit
    {
        get { return s_Unit; }
    }
}

其使用方式如下

Meter distanceHome = new Meter(10000);
Kilometer distanceInKMs;

Distance.Convert(distanceHome, out distanceInKMs);   //  distanceInKMs.Value = 10

The first which comes to mind is to have something like System.TimeSpan where the same class represents time and you access it in different units via properties.

You would store the value internally in some constant unit (presumably SI) and convert it in the property getter / setter:

Distance d = new Distance;
d.Meters = 5000;
var km = d.Kilometers; // km = 5;

Or you can create classes for each unit:

public sealed class DistanceUnit
{
    public DistanceUnit(string name, string symbol, double scale)
    {
        Name = name;
        Symbol = symbol;
        Scale = scale;
    }

    public string Name { get; private set; }
    public string Symbol { get; private set; }
    public double Scale { get; private set; }
}


public abstract class Distance
{
    protected Distance(double value)
    {
        this.Value = value;
    }

    protected Distance()
    {
    }

    public double Value { get; set; }

    public abstract DistanceUnit Unit { get; }

    public override string ToString()
    {
        return this.Value + " " + Unit.Symbol;
    }


    public static void Convert<TIn, TOut>(TIn original, out TOut result)
        where TIn : Distance, new()
        where TOut : Distance, new()
    {

        result = new TOut();

        var scale = result.Unit.Scale / original.Unit.Scale;

        result.Value = original.Value * scale;
    }

}

public sealed class Meter : Distance
{

    private static readonly DistanceUnit s_Unit = new DistanceUnit("Meter", "m", 1);

    public Meter(double value) : base(value)
    {
    }

    public Meter()
    {
    }

    public override DistanceUnit Unit
    {
        get { return s_Unit; }

    }
}

public sealed class Kilometer : Distance
{
    private static readonly DistanceUnit s_Unit = new DistanceUnit("Kilometer", "km", .001);

    public Kilometer()
    {
    }

    public Kilometer(double value)
        : base(value)
    {
    }

    public override DistanceUnit Unit
    {
        get { return s_Unit; }
    }
}

which is used like

Meter distanceHome = new Meter(10000);
Kilometer distanceInKMs;

Distance.Convert(distanceHome, out distanceInKMs);   //  distanceInKMs.Value = 10
甜妞爱困 2024-08-24 04:42:59

有很多不同的方法可以解决这个问题。这是使用委托的一种方法。

public class Converter
{
    public static double Convert(double original, Func<double, double> conversion)
    {
        return conversion(original);
    }
}

public class SizeConverter
{
    public static double MegabytesToBytes(double megabytes)
    {
        return megabytes * 1048576;
    }

    public static double KilobytesToBytes(double kilobytes)
    {
        return kilobytes * 1024;
    }
}

您可以这样使用它:

        double result1 = Converter.Convert(2, SizeConverter.MegabytesToBytes);
        double result2 = Converter.Convert(2, SizeConverter.KilobytesToBytes);

如果您需要除双精度之外的其他类型,则需要重载 Convert 方法。

There are a lot of different ways you could approach this. Here is one way using delegates.

public class Converter
{
    public static double Convert(double original, Func<double, double> conversion)
    {
        return conversion(original);
    }
}

public class SizeConverter
{
    public static double MegabytesToBytes(double megabytes)
    {
        return megabytes * 1048576;
    }

    public static double KilobytesToBytes(double kilobytes)
    {
        return kilobytes * 1024;
    }
}

You'd use this like this:

        double result1 = Converter.Convert(2, SizeConverter.MegabytesToBytes);
        double result2 = Converter.Convert(2, SizeConverter.KilobytesToBytes);

If you need other types other than doubles, you'll need to overload the Convert method.

泪是无色的血 2024-08-24 04:42:59

考虑一下您希望如何使用它,并让它指导您。例如,您想表示什么类型的计量单位?你的基本单位是什么?计量单位之间的换算应该如何处理?

我想我们马上就可以看到你需要某种方式来表示测量单位,例如英尺、米、升、弗隆、度、千克、磅、居里、欧姆等。这似乎是一个类,或一系列类 - 也许以单位为基础,以英尺、米、升、弗隆为子类。然后我认为您需要某种方法将单位与值关联起来。这个单位/值必须提供某种方式在相同类型的测量单位(长度/距离、体积、温度、质量/重量)之间进行转换,并且足够明亮,以便在调用代码尝试一些可疑的事情时抛出合理的异常(例如将 27 摄氏度转换为英里/小时)。一些创建单位/值实例的便捷方法会很方便。单位/价值事物不应该与特定种类或类别的单位联系在一起,而应该能够愉快地处理您想要扔给它的任何单位。

从代码角度来说,我认为这样的东西会很棒:

UnitValue a, b, c;

a = new UnitValue(3 * 5280, Feet);
b = new UnitValue(180, Seconds);
c = (a / b).As(Miles / Hours);
cout << c;

应该希望打印类似的东西

60 miles/hour

所以你可以看到将一个UnitValue除以另一个UnitValue应该产生一个带有复合单位的新UnitValue - 在这种情况下,a / b< /code> 应生成单位为英尺每秒(英尺/秒)的 UnitValue,然后转换例程 As 将其转换为其他值,在本例中为英里每小时。

我希望这有助于激发您的一些思考。

分享并享受。

Think about how you would want to use this, and let that guide you. For example, what kinds of units of measure do you want to represent? What are your base units going to be? How should conversions between units of measure be handled?

Right off I think we can see that you're going to need some way to represent a unit of measurement, e.g. feet, meters, liters, furlongs, degrees, kilograms, pounds, curies, ohms, etc. That appears to be a class, or a series of classes - perhaps Unit as the base, with Feet, Meters, Liters, Furlongs as subclasses. Then I think you'll need some way to associate a unit with a value. This unit/value will have to provide some way to convert between units of measure of the same type (length/distance, volume, temperature, mass/weight) and be bright enough to throw a reasonable exception if the calling code tries something fishy (such as converting 27 degrees Celsius to miles/hour). Some convenient way to create unit/value instances would be handy. The unit/value thing shouldn't be tied to a particular kind or class of unit, but should happily be able to handle any unit you care to throw at it.

Codewise I'd think something like this would be great:

UnitValue a, b, c;

a = new UnitValue(3 * 5280, Feet);
b = new UnitValue(180, Seconds);
c = (a / b).As(Miles / Hours);
cout << c;

should hopefully print something like

60 miles/hour

So you can see that dividing one UnitValue by another UnitValue should produce a new UnitValue with a compound unit - in this case, the a / b should produce a UnitValue with units of Feet per Seconds (feet / seconds), which the conversion routine As then converts to something else, in this case miles per hour.

I hope this helps spark some thinking on your part.

Share and enjoy.

我的影子我的梦 2024-08-24 04:42:59

我只是通过使用矩阵来完成类似的事情

public static class Units
{
    public enum MassUnits
    {
        grams,
        kg,
        lb,
        mg,
        oz
    }
    static readonly double[,] MassConversions = new double[5, 5]
    {   //grams     kg              lb          mg          oz
            {1d,        1/1000d,        1/453.592d, 1000d,      1/28.3495d},    //grams
            {1000d,     1d,             2.20462d,   1000000d,   35.274d},       //kg
            {453.592d,  1/2.20462d,     1d,         453592d,    16d},           //lb
            {1/1000d,   1/1000000d,     1/453592d,  1d,         1/28349.5d},    //mg
            {28.3495d,  1/35.274d,      1/16d,      28349.5d,   1}             //oz
    };

    public static double ConvertQuantity(this double oldQty, MassUnits oldUnit, MassUnits newUnit, int decimals = 2)
    {
        return ConvertQuantity(oldQty, MassConversions[(int)oldUnit, (int)newUnit], decimals);
    }

    public static double ConvertQuantity(this double oldQty, double conversion, int decimals = 2)
    {
        return Math.Round(oldQty * conversion, decimals);
    }

    public static void test()
    {
        var kilos = 5.2;
        var pounds = kilos.ConvertQuantity(MassUnits.kg, MassUnits.lb);
    }
}

I just accomplish something similar by using matrices

public static class Units
{
    public enum MassUnits
    {
        grams,
        kg,
        lb,
        mg,
        oz
    }
    static readonly double[,] MassConversions = new double[5, 5]
    {   //grams     kg              lb          mg          oz
            {1d,        1/1000d,        1/453.592d, 1000d,      1/28.3495d},    //grams
            {1000d,     1d,             2.20462d,   1000000d,   35.274d},       //kg
            {453.592d,  1/2.20462d,     1d,         453592d,    16d},           //lb
            {1/1000d,   1/1000000d,     1/453592d,  1d,         1/28349.5d},    //mg
            {28.3495d,  1/35.274d,      1/16d,      28349.5d,   1}             //oz
    };

    public static double ConvertQuantity(this double oldQty, MassUnits oldUnit, MassUnits newUnit, int decimals = 2)
    {
        return ConvertQuantity(oldQty, MassConversions[(int)oldUnit, (int)newUnit], decimals);
    }

    public static double ConvertQuantity(this double oldQty, double conversion, int decimals = 2)
    {
        return Math.Round(oldQty * conversion, decimals);
    }

    public static void test()
    {
        var kilos = 5.2;
        var pounds = kilos.ConvertQuantity(MassUnits.kg, MassUnits.lb);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文