protected MetricUnit()
        {
            //access the SIUnitAttribute
            MemberInfo info = this.GetType();

            object[] attributes = (object[])info.GetCustomAttributes(true);

            //get the UnitAttribute
            MetricUnitAttribute siua = (MetricUnitAttribute)attributes.SingleOrDefault <object>(ut => ut is MetricUnitAttribute);

            if (siua != null)
            {
                defaultUnitPrefix = MetricPrefix.FromPrefixName(siua.SiPrefix.ToString());
                unitPrefix        = MetricPrefix.FromPrefixName(siua.SiPrefix.ToString());
            }
            else
            {
                throw new UnitException("SIUnitAttribute Not Found");
            }


            //ReferenceUnit attribute may or may not appear
            // if it appears then the unit is not a default SI unit
            // but act as SI Unit {means take prefixes}.  and accepted by the SI poids
            // however the code of reference unit is in the base class code.
        }
        public static MetricPrefix Divide(MetricPrefix firstPrefix, MetricPrefix secondPrefix)
        {
            int exp = firstPrefix.Exponent / secondPrefix.Exponent;

            CheckExponent(exp);

            MetricPrefix prefix = MetricPrefix.FromExponent(exp);

            return(prefix);
        }
Beispiel #3
0
        private static AnyQuantity <double> MakeQuantity(MetricUnit unit, MetricPrefix siPrefix, double value)
        {
            //assign its prefix
            unit.UnitPrefix = siPrefix;

            //create the corresponding quantity
            AnyQuantity <double> qty = unit.GetThisUnitQuantity <double>();

            //assign the unit to the created quantity
            qty.Unit = unit;

            //assign the value to the quantity
            qty.Value = value;

            return(qty);
        }
        /// <summary>
        /// Check the exponent if it can found or
        /// if it exceeds 24 or precedes -25 <see cref="MetricPrefixException"/> occur with the closest
        /// <see cref="MetricPrefix"/> and overflow the rest of it.
        /// </summary>
        /// <param name="exp"></param>
        public static void CheckExponent(double expo)
        {
            int exp = (int)Math.Floor(expo);

            double ov = expo - exp;

            if (exp > 24)
            {
                throw new MetricPrefixException("Exponent Exceed 24")
                      {
                          WrongExponent    = exp,
                          CorrectPrefix    = MetricPrefix.FromExponent(24),
                          OverflowExponent = (exp - 24) + ov
                      }
            }
            ;

            if (exp < -24)
            {
                throw new MetricPrefixException("Exponent Precede -24")
                      {
                          WrongExponent    = exp,
                          CorrectPrefix    = MetricPrefix.FromExponent(-24),
                          OverflowExponent = (exp + 24) + ov
                      }
            }
            ;

            int[] wrongexp   = { 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23 };
            int[] correctexp = { 3, 3, 6, 6, 9, 9, 12, 12, 15, 15, 18, 18, 21, 21 };

            for (int i = 0; i < wrongexp.Length; i++)
            {
                //find if exponent in wrong powers
                if (Math.Abs(exp) == wrongexp[i])
                {
                    int cexp = 0;
                    if (exp > 0)
                    {
                        cexp = correctexp[i];
                    }
                    if (exp < 0)
                    {
                        cexp = -1 * correctexp[i];
                    }


                    throw new MetricPrefixException("Exponent not aligned")
                          {
                              WrongExponent    = exp,
                              CorrectPrefix    = MetricPrefix.FromExponent(cexp),
                              OverflowExponent = (exp - cexp) + ov     //5-3 = 2  ,  -5--3 =-2
                          };
                }
            }


            if (ov != 0)
            {
                //then the exponent must be 0.5
                throw new MetricPrefixException("Exponent not aligned")
                      {
                          WrongExponent    = exp,
                          CorrectPrefix    = MetricPrefix.FromExponent(0),
                          OverflowExponent = ov     //5-3 = 2  ,  -5--3 =-2
                      };
            }
        }
    }
}
 /// <summary>
 /// Gets the factor to convert to the required prefix.
 /// </summary>
 /// <param name="prefix"></param>
 /// <returns>Conversion factor</returns>
 public double GetFactorForConvertTo(MetricPrefix prefix)
 {
     return(prefix.Factor / this.Factor);
 }
 public MetricPrefix Invert()
 {
     return(MetricPrefix.FromExponent(0 - this.PrefixExponent));
 }
Beispiel #7
0
        /// <summary>
        /// Group all similar units so it remove units that reached exponent zero
        /// also keep track of prefixes of metric units.
        /// </summary>
        /// <param name="bulk_units"></param>
        /// <returns></returns>
        private List <Unit> GroupUnits(List <Unit> bulk_units)
        {
            List <Unit> units = FlattenUnits(bulk_units);

            if (units.Count == 1)
            {
                return(units);
            }



            List <Unit> GroupedUnits = new List <Unit>();


            Dictionary <Type, Unit> us = new Dictionary <Type, Unit>();

            foreach (Unit un in units)
            {
                if (us.ContainsKey(un.GetType()))
                {
                    //check for prefixes before accumulating units
                    //   otherwise I'll lose the UnitExponent value.
                    if (un is MetricUnit)
                    {
                        //check prefixes to consider milli+Mega for example for overflow

                        MetricPrefix accumPrefix  = ((MetricUnit)us[un.GetType()]).UnitPrefix;
                        MetricPrefix sourcePrefix = ((MetricUnit)un).UnitPrefix;

                        try
                        {
                            //Word about MetricPrefix
                            //   The prefix takes the unit exponent as another exponent to it
                            //  so if we are talking about cm^2 actually it is c^2*m^2
                            //  suppose we multiply cm*cm this will give cm^2
                            //     so no need to alter the prefix value
                            // however remain a problem of different prefixes
                            // for example km * cm = ?m^2
                            //  k*c = ?^2
                            //    so ? = (k+c)/2  ;)
                            //  if there is a fraction remove the prefixes totally and substitute them
                            //  in the overflow flag.

                            // about division
                            // km / cm = ?<1>
                            // k/c = ?   or in exponent k-c=?


                            double targetExponent = us[un.GetType()].unitExponent + un.unitExponent;

                            double accumExponent  = accumPrefix.Exponent * us[un.GetType()].unitExponent;
                            double sourceExponent = sourcePrefix.Exponent * un.unitExponent;

                            double resultExponent = (accumExponent + sourceExponent);

                            if (!(us[un.GetType()].IsInverted ^ un.IsInverted))
                            {
                                //multiplication


                                if (resultExponent % targetExponent == 0)
                                {
                                    //we can get the symbol of the sqrt of this
                                    double unknown = resultExponent / targetExponent;

                                    ((MetricUnit)us[un.GetType()]).UnitPrefix = MetricPrefix.FromExponent(unknown);
                                }
                                else
                                {
                                    //we can't get the approriate symbol because we have a fraction
                                    // like  kilo * centi = 3-2=1    1/2=0.5   or 1%2=1
                                    // so we will take the whole fraction and make an overflow

                                    ((MetricUnit)us[un.GetType()]).UnitPrefix = MetricPrefix.None;
                                    if (resultExponent != 0)
                                    {
                                        unitOverflow += Math.Pow(10, resultExponent);
                                        _IsOverflowed = true;
                                    }
                                }
                            }
                            else
                            {
                                //division
                                //resultExponent = (accumExponent - sourceExponent);

                                ((MetricUnit)us[un.GetType()]).UnitPrefix = MetricPrefix.None;

                                if (resultExponent != 0)   //don't overflow in case of zero exponent target because there is not prefix in this case
                                {
                                    unitOverflow += Math.Pow(10, resultExponent);
                                    _IsOverflowed = true;
                                }
                            }
                        }
                        catch (MetricPrefixException mpe)
                        {
                            ((MetricUnit)us[un.GetType()]).UnitPrefix = mpe.CorrectPrefix;
                            unitOverflow += Math.Pow(10, mpe.OverflowExponent);
                            _IsOverflowed = true;
                        }
                    }
                    us[un.GetType()].UnitExponent  += un.UnitExponent;
                    us[un.GetType()].UnitDimension += un.UnitDimension;
                }
                else
                {
                    us[un.GetType()] = (Unit)un.MemberwiseClone();
                }
            }
            foreach (Unit un in us.Values)
            {
                if (un.UnitExponent != 0)
                {
                    GroupedUnits.Add(un);
                }
                else
                {
                    //zero means units should be skipped
                    // however we are testing for prefix if the unit is metric
                    //  if the unit is metric and deprecated the prefix should be taken into consideration
                    if (un is MetricUnit)
                    {
                        MetricUnit mu = (MetricUnit)un;
                        if (mu.UnitPrefix.Exponent != 0)
                        {
                            _IsOverflowed = true;
                            unitOverflow += Math.Pow(10, mu.UnitPrefix.Exponent);
                        }
                    }
                }
            }

            return(GroupedUnits);
        }
        /// <summary>
        /// Returns the unit corresponding to the passed string.
        /// Suppors units with exponent.
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        internal static Unit ParseUnit(string un)
        {
            if (un == "1")
            {
                //this is dimensionless value
                return(new Unit(typeof(Quantities.DimensionlessQuantities.DimensionlessQuantity <>)));
            }

            //find '^'

            string[] upower = un.Split('^');


            string unit = upower[0];

            int power = 1;

            if (upower.Length > 1)
            {
                power = int.Parse(upower[1], CultureInfo.InvariantCulture);
            }

            Unit FinalUnit = null;

            //Phase 1: try direct mapping.
            try
            {
                FinalUnit = FindUnit(unit);
            }
            catch (UnitNotFoundException)
            {
                //try to find if it as a Metric unit with prefix
                //loop through all prefixes.
                for (int i = 10; i >= -10; i -= 1)
                {
                    if (i == 0)
                    {
                        i--;         //skip the None prefix
                    }
                    if (unit.StartsWith(MetricPrefix.GetPrefix(i).Symbol, StringComparison.Ordinal))
                    {
                        //found

                        MetricPrefix mp    = MetricPrefix.GetPrefix(i);
                        string       upart = unit.Substring(mp.Symbol.Length);

                        //then it should be MetricUnit otherwise die :)

                        MetricUnit u = FindUnit(upart) as MetricUnit;

                        if (u == null)
                        {
                            goto nounit;
                        }

                        u.UnitPrefix = mp;

                        FinalUnit = u;
                        break;
                    }
                }
            }


            if (FinalUnit == null)
            {
                goto nounit;
            }

            if (power > 1)
            {
                //discover the new type
                QuantityDimension ud = FinalUnit.UnitDimension * power;

                Unit[] chobits = new Unit[power];  //what is chobits any way :O

                for (int iy = 0; iy < power; iy++)
                {
                    chobits[iy] = (Unit)FinalUnit.MemberwiseClone();
                }


                Type uQType = null;

                uQType = QuantityDimension.GetQuantityTypeFrom(ud);


                FinalUnit = new Unit(uQType, chobits);
            }

            return(FinalUnit);



nounit:
            throw new UnitNotFoundException(un);
        }