예제 #1
0
        /// <summary>
        /// Divides the right unit from the left unit: <paramref name="Left"/>/<paramref name="Right"/>.
        /// </summary>
        /// <param name="Left">Left unit.</param>
        /// <param name="Right">Right unit.</param>
        /// <param name="ResidueExponent">Any residual exponent resulting from the division.</param>
        /// <returns>Resulting unit.</returns>
        public static Unit Divide(Unit Left, Unit Right, out int ResidueExponent)
        {
            LinkedList <KeyValuePair <AtomicUnit, int> > Result = new LinkedList <KeyValuePair <AtomicUnit, int> >();
            int    LeftExponent   = Prefixes.PrefixToExponent(Left.prefix);
            int    RightExponent  = Prefixes.PrefixToExponent(Right.prefix);
            int    ResultExponent = LeftExponent - RightExponent;
            Prefix ResultPrefix   = Prefixes.ExponentToPrefix(ResultExponent, out ResidueExponent);
            LinkedListNode <KeyValuePair <AtomicUnit, int> > Loop;
            string Name;
            int    Exponent;
            bool   Found;

            foreach (KeyValuePair <AtomicUnit, int> Factor in Left.factors)
            {
                Result.AddLast(Factor);
            }

            foreach (KeyValuePair <AtomicUnit, int> Factor in Right.factors)
            {
                Name  = Factor.Key.Name;
                Loop  = Result.First;
                Found = false;

                while (!(Loop is null) && !Found)
                {
                    if (Loop.Value.Key.Name == Name)
                    {
                        Found    = true;
                        Exponent = Loop.Value.Value - Factor.Value;
                        if (Exponent == 0)
                        {
                            Result.Remove(Loop);
                        }
                        else
                        {
                            Loop.Value = new KeyValuePair <AtomicUnit, int>(Loop.Value.Key, Exponent);
                        }
                    }
                    else
                    {
                        Loop = Loop.Next;
                    }
                }

                if (Found)
                {
                    continue;
                }

                Result.AddLast(new KeyValuePair <AtomicUnit, int>(Factor.Key, -Factor.Value));
            }

            return(new Unit(ResultPrefix, Result));
        }
예제 #2
0
        /// <summary>
        /// Inverts the unit.
        /// </summary>
        /// <param name="ResidueExponent">Any exponential residue. If this value is 0, it means the exponent corresponds exactly
        /// to the returned prefix.</param>
        /// <returns>Inverted unit.</returns>
        public Unit Invert(out int ResidueExponent)
        {
            int Exponent = Prefixes.PrefixToExponent(this.prefix);
            LinkedList <KeyValuePair <AtomicUnit, int> > Factors = new LinkedList <KeyValuePair <AtomicUnit, int> >();

            foreach (KeyValuePair <AtomicUnit, int> Factor in this.factors)
            {
                Factors.AddLast(new KeyValuePair <AtomicUnit, int>(Factor.Key, -Factor.Value));
            }

            return(new Unit(Prefixes.ExponentToPrefix(-Exponent, out ResidueExponent), Factors));
        }
예제 #3
0
        /// <summary>
        /// Tries to convert a magnitude in one unit to a magnitude in another.
        /// </summary>
        /// <param name="From">Original magnitude.</param>
        /// <param name="FromUnit">Original unit.</param>
        /// <param name="ToUnit">Desired unit.</param>
        /// <param name="To">Converted magnitude.</param>
        /// <returns>If conversion was successful.</returns>
        public static bool TryConvert(double From, Unit FromUnit, Unit ToUnit, out double To)
        {
            if (FromUnit.Equals(ToUnit))
            {
                To = From;
                return(true);
            }

            FromUnit = FromUnit.ToReferenceUnits(ref From);
            To       = From;
            ToUnit   = ToUnit.FromReferenceUnits(ref To);

            Unit Div = Unit.Divide(FromUnit, ToUnit, out int Exponent);

            Exponent += Prefixes.PrefixToExponent(Div.prefix);
            if (Exponent != 0)
            {
                To *= Math.Pow(10, Exponent);
            }

            return(!Div.HasFactors);
        }
예제 #4
0
        /// <summary>
        /// Converts the unit to a series of reference unit factors. (Unrecognized units will be assumed to be reference units.)
        /// </summary>
        /// <param name="Magnitude">Reference magnitude.</param>
        /// <returns>Unit consisting of reference unit factors.</returns>
        public Unit FromReferenceUnits(ref double Magnitude)
        {
            if (this.hasReferenceUnits)
            {
                return(this);
            }

            lock (synchObject)
            {
                if (baseUnits is null)
                {
                    Search();
                }

                bool HasNonReference = false;

                foreach (KeyValuePair <AtomicUnit, int> Factor in this.factors)
                {
                    if (!referenceUnits.ContainsKey(Factor.Key.Name))
                    {
                        HasNonReference = true;
                        break;
                    }
                }

                if (HasNonReference)
                {
                    LinkedList <KeyValuePair <AtomicUnit, int> > ReferenceFactors = new LinkedList <KeyValuePair <AtomicUnit, int> >();
                    int    Exponent = Prefixes.PrefixToExponent(this.prefix);
                    int    FactorExponent;
                    string Name;

                    foreach (KeyValuePair <AtomicUnit, int> Factor in this.factors)
                    {
                        FactorExponent = Factor.Value;

                        if (referenceUnits.ContainsKey(Name = Factor.Key.Name))
                        {
                            this.Add(ReferenceFactors, Factor.Key, Factor.Value);
                        }
                        else if (baseUnits.TryGetValue(Name, out IBaseQuantity BaseQuantity))
                        {
                            if (BaseQuantity.FromReferenceUnit(ref Magnitude, Name, FactorExponent))
                            {
                                this.Add(ReferenceFactors, BaseQuantity.ReferenceUnit, FactorExponent);
                            }
                            else
                            {
                                this.Add(ReferenceFactors, Factor.Key, Factor.Value);
                            }
                        }
                        else if (derivedUnits.TryGetValue(Name, out PhysicalQuantity Quantity))
                        {
                            Magnitude *= Math.Pow(Quantity.Magnitude, FactorExponent);
                            Exponent  += Prefixes.PrefixToExponent(Quantity.Unit.prefix) * FactorExponent;

                            foreach (KeyValuePair <AtomicUnit, int> Segment in Quantity.Unit.factors)
                            {
                                if (referenceUnits.ContainsKey(Name = Segment.Key.Name))
                                {
                                    this.Add(ReferenceFactors, Segment.Key, Segment.Value * FactorExponent);
                                }
                                else if (baseUnits.TryGetValue(Name, out BaseQuantity))
                                {
                                    if (BaseQuantity.FromReferenceUnit(ref Magnitude, Name, Segment.Value * FactorExponent))
                                    {
                                        this.Add(ReferenceFactors, BaseQuantity.ReferenceUnit, Segment.Value * FactorExponent);
                                    }
                                    else
                                    {
                                        this.Add(ReferenceFactors, Segment.Key, Segment.Value * FactorExponent);
                                    }
                                }
                                else
                                {
                                    this.Add(ReferenceFactors, Segment.Key, Segment.Value * FactorExponent);
                                }
                            }
                        }
                        else if (compoundUnits.TryGetValue(Name, out KeyValuePair <AtomicUnit, int>[] Units))
                        {
                            foreach (KeyValuePair <AtomicUnit, int> Segment in Units)
                            {
                                if (referenceUnits.ContainsKey(Name = Segment.Key.Name))
                                {
                                    this.Add(ReferenceFactors, Segment.Key, Segment.Value * FactorExponent);
                                }
                                else if (baseUnits.TryGetValue(Name, out BaseQuantity))
                                {
                                    if (BaseQuantity.FromReferenceUnit(ref Magnitude, Name, Segment.Value * FactorExponent))
                                    {
                                        this.Add(ReferenceFactors, BaseQuantity.ReferenceUnit, Segment.Value * FactorExponent);
                                    }
                                    else
                                    {
                                        this.Add(ReferenceFactors, Segment.Key, Segment.Value * FactorExponent);
                                    }
                                }
                                else
                                {
                                    this.Add(ReferenceFactors, Segment.Key, Segment.Value * FactorExponent);
                                }
                            }
                        }
                        else
                        {
                            this.Add(ReferenceFactors, Factor.Key, Factor.Value);
                        }
                    }

                    Unit Result = new Unit(Prefixes.ExponentToPrefix(Exponent, out FactorExponent), ReferenceFactors);
                    if (FactorExponent != 0)
                    {
                        Magnitude *= Math.Pow(10, FactorExponent);
                    }

                    Result.hasBaseUnits      = true;
                    Result.hasReferenceUnits = true;

                    return(Result);
                }
                else
                {
                    this.hasBaseUnits      = true;
                    this.hasReferenceUnits = true;
                    return(this);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Converts the unit to a string.
        /// </summary>
        /// <param name="IncludePrefix">If the prefix should be included in the string or not.</param>
        public string ToString(bool IncludePrefix)
        {
            StringBuilder Numerator      = null;
            StringBuilder Denominator    = null;
            int           NrDenominators = 0;

            foreach (KeyValuePair <AtomicUnit, int> Factor in this.factors)
            {
                if (Factor.Value > 0)
                {
                    if (Numerator is null)
                    {
                        if (IncludePrefix)
                        {
                            Numerator = new StringBuilder(Prefixes.ToString(this.prefix));
                        }
                        else
                        {
                            Numerator = new StringBuilder();
                        }
                    }
                    else
                    {
                        Numerator.Append('⋅');
                    }

                    Numerator.Append(Factor.Key.Name);

                    if (Factor.Value > 1)
                    {
                        if (Factor.Value == 2)
                        {
                            Numerator.Append('²');
                        }
                        else if (Factor.Value == 3)
                        {
                            Numerator.Append('³');
                        }
                        else
                        {
                            Numerator.Append('^');
                            Numerator.Append(Factor.Value.ToString());
                        }
                    }
                }
                else
                {
                    if (Denominator is null)
                    {
                        Denominator = new StringBuilder();
                    }
                    else
                    {
                        Denominator.Append('⋅');
                    }

                    NrDenominators++;
                    Denominator.Append(Factor.Key.Name);

                    if (Factor.Value < -1)
                    {
                        if (Factor.Value == -2)
                        {
                            Denominator.Append('²');
                        }
                        else if (Factor.Value == -3)
                        {
                            Denominator.Append('³');
                        }
                        else
                        {
                            Denominator.Append('^');
                            Denominator.Append((-Factor.Value).ToString());
                        }
                    }
                }
            }

            if (Numerator is null)
            {
                if (IncludePrefix)
                {
                    Numerator = new StringBuilder(Prefixes.ToString(this.prefix));
                }
                else
                {
                    Numerator = new StringBuilder();
                }
            }

            if (!(Denominator is null))
            {
                Numerator.Append('/');

                if (NrDenominators > 1)
                {
                    Numerator.Append('(');
                }

                Numerator.Append(Denominator.ToString());

                if (NrDenominators > 1)
                {
                    Numerator.Append(')');
                }
            }

            return(Numerator.ToString());
        }