SORU
8 Aralık 2008, PAZARTESİ


C ölçü birimleri# - neredeyse

Units of Measure in F#, ilham ve bunu yapamayacağını (here) ileri sürerek rağmen C# ben bir fikrim yoktu etrafında oynuyorum diğer gün.

namespace UnitsOfMeasure
{
    public interface IUnit { }
    public static class Length
    {
        public interface ILength : IUnit { }
        public class m : ILength { }
        public class mm : ILength { }
        public class ft : ILength { }
    }
    public class Mass
    {
        public interface IMass : IUnit { }
        public class kg : IMass { }
        public class g : IMass { }
        public class lb : IMass { }
    }

    public class UnitDouble<T> where T : IUnit
    {
        public readonly double Value;
        public UnitDouble(double value)
        {
            Value = value;
        }
        public static UnitDouble<T> operator  (UnitDouble<T> first, UnitDouble<T> second)
        {
            return new UnitDouble<T>(first.Value   second.Value);
        }
        //TODO: minus operator/equality
    }
}

Örnek kullanım:

var a = new UnitDouble<Length.m>(3.1);
var b = new UnitDouble<Length.m>(4.9);
var d = new UnitDouble<Mass.kg>(3.4);
Console.WriteLine((a   b).Value);
//Console.WriteLine((a   c).Value); <-- Compiler says no

Bir sonraki adım dönüşüm (snippet) uygulamaya çalışıyorum

public interface IUnit { double toBase { get; } }
public static class Length
{
    public interface ILength : IUnit { }
    public class m : ILength { public double toBase { get { return 1.0;} } }
    public class mm : ILength { public double toBase { get { return 1000.0; } } }
    public class ft : ILength { public double toBase { get { return 0.3048; } } }
    public static UnitDouble<R> Convert<T, R>(UnitDouble<T> input) where T : ILength, new() where R : ILength, new()
    {
        double mult = (new T() as IUnit).toBase;
        double div = (new R() as IUnit).toBase;
        return new UnitDouble<R>(input.Value * mult / div);
    }
}

(Statik, ama biz tüm 16 **bildiğiniz gibi)kullanarak nesneleri başlatmasını önlemek için isterdim O zaman bunu yapabilirsiniz:

var e = Length.Convert<Length.mm, Length.m>(c);
var f = Length.Convert<Length.mm, Mass.kg>(d); <-- but not this

Belli ki, bu büyük bir boşluk, F göre " ölçü birimi (seni işe bırakayım).

Oh, soru şu: sen bu işe ne diyorsun? Kullanmaya değer mi? Başkası zaten daha iyi yaptı?

GÜNCELLEMEinsanlar bu konu ile ilgilenen, here 1997 bir kağıt çözüm farklı bir tür tartışmak için bir bağlantı için (özellikle C#)

CEVAP
8 Aralık 2008, PAZARTESİ


Kayıp boyut analizi. F örneğin (bu cevap size bağlı),# bunu yapabilirsiniz:

let g = 9.8<m/s^2>

ve ivme, yeni bir birim, metre ve saniye (aslında C şablonlarını kullanarak aynı şeyi yapabilirsiniz) elde oluşturun.

C#, Olası zamanında boyutlu analiz yapmak çok önemlidir, ama havai ekler ve derleme yararı kontrol vermez. Yapmanın bir yolu yok bildiğim kadarıyla derleme birimleri C tam#.

Yapmaya değer olup olmadığını tabii ki uygulamaya göre değişir, ancak birçok bilimsel uygulamalar için kesinlikle iyi bir fikirdir. Varolan kütüphaneler için bilmiyorum .NET, ama büyük ihtimalle yok.

Eğer zamanında bunu nasıl ilgileniyorsanız, fikri her değeri skaler bir değer ve tamsayılar her temel birimi gücünü temsil eder.

class Unit
{
    double scalar;
    int kg;
    int m;
    int s;
    // ... for each basic unit

    public Unit(double scalar, int kg, int m, int s)
    {
       this.scalar = scalar;
       this.kg = kg;
       this.m = m;
       this.s = s;
       ...
    }

    // For addition/subtraction, exponents must match
    public static Unit operator  (Unit first, Unit second)
    {
        if (UnitsAreCompatible(first, second))
        {
            return new Unit(
                first.scalar   second.scalar,
                first.kg,
                first.m,
                first.s,
                ...
            );
        }
        else
        {
            throw new Exception("Units must match for addition");
        }
    }

    // For multiplication/division, add/subtract the exponents
    public static Unit operator *(Unit first, Unit second)
    {
        return new Unit(
            first.scalar * second.scalar,
            first.kg   second.kg,
            first.m   second.m,
            first.s   second.s,
            ...
        );
    }

    public static bool UnitsAreCompatible(Unit first, Unit second)
    {
        return
            first.kg == second.kg &&
            first.m == second.m &&
            first.s == second.s
            ...;
    }
}

Eğer kullanıcı birimi (iyi bir fikir neyse) değerini değiştirmek için izin ver eğer doğru değilse, ortak birimler için alt ekleyebilirsiniz:

class Speed : Unit
{
    public Speed(double x) : base(x, 0, 1, -1, ...); // m/s => m^1 * s^-1
    {
    }
}

class Acceleration : Unit
{
    public Acceleration(double x) : base(x, 0, 1, -2, ...); // m/s^2 => m^1 * s^-2
    {
    }
}

Ayrıca türetilmiş bir tür ortak türleri uyumlu birimleri denetlemesini önlemek için daha özel operatörler tanımlayabilirsiniz.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • CNET

    CNET

    5 Mayıs 2006
  • sknbp

    sknbp

    16 Kasım 2006
  • SunsetTrance

    SunsetTrance

    20 EYLÜL 2008