public static MetricPrefix Divide(MetricPrefix firstPrefix, MetricPrefix secondPrefix)
        {
            int exp = firstPrefix.Exponent / secondPrefix.Exponent;

            CheckExponent(exp);

            MetricPrefix prefix = MetricPrefix.FromExponent(exp);

            return(prefix);
        }
        /// <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
                      };
            }
        }
    }
}
 public MetricPrefix Invert()
 {
     return(MetricPrefix.FromExponent(0 - this.PrefixExponent));
 }
Example #4
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);
        }