Skip to main content

C# extension methods for the Double class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ExtensionOverflow
{
    /// <summary>
    /// Double Extensions
    /// </summary>
    public static class DoubleExtensions
    {
        #region PercentageOf calculations

        public static decimal PercentageOf(this double number, int percent)
        {
            return (decimal)(number * percent / 100);
        }

        public static decimal PercentageOf(this double number, float percent)
        {
            return (decimal)(number * percent / 100);
        }

        public static decimal PercentageOf(this double number, double percent)
        {
            return (decimal)(number * percent / 100);
        }

        public static decimal PercentageOf(this double number, long percent)
        {
            return (decimal)(number * percent / 100);
        }

        public static decimal PercentOf(this double position, int total)
        {
            decimal result = 0;
            if (position > 0 && total > 0)
            {
                result = (decimal)((decimal)position / (decimal)total * 100);
            }
            return result;
        }

        public static decimal PercentOf(this double position, float total)
        {
            decimal result = 0;
            if (position > 0 && total > 0)
            {
                result = (decimal)((decimal)position / (decimal)total * 100);
            }
            return result;
        }

        public static decimal PercentOf(this double position, double total)
        {
            decimal result = 0;
            if (position > 0 && total > 0)
            {
                result = (decimal)((decimal)position / (decimal)total * 100);
            }
            return result;
        }

        public static decimal PercentOf(this double position, long total)
        {
            decimal result = 0;
            if (position > 0 && total > 0)
            {
                result = (decimal)((decimal)position / (decimal)total * 100);
            }
            return result;
        }

        #endregion

        /// <summary>
        /// Extension method to round a double value to a fixed number of significant figures instead of a fixed decimal places.
        /// </summary>
        /// <param name="d">Double we're rounding</param>
        /// <param name="digits">Number of significant figures</param>
        /// <returns>New double rounded to digits-significant figures</returns>
        public static double RoundToSignificantDigits(this double d, int digits)
        {
            if (d == 0) return 0;
            var scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(d))) + 1);
            return scale * Math.Round(d / scale, digits);
        }

        /// <summary>
        /// Casts the specified input value to a decimal while acknowledging the overflow conditions
        /// </summary>
        /// <param name="input">The value to be cast</param>
        /// <returns>The input value as a decimal, if the value is too large or to small to be represented
        /// as a decimal, then the closest decimal value will be returned</returns>
        public static decimal SafeDecimalCast(this double input)
        {
            if (input <= (double) decimal.MinValue) return decimal.MinValue;
            if (input >= (double) decimal.MaxValue) return decimal.MaxValue;
            return (decimal) input;
        }

        /// <summary>
        /// Check if a number is NaN or equal to zero
        /// </summary>
        /// <param name="value">The double value to check</param>
        public static bool IsNaNOrZero(this double value)
        {
            return double.IsNaN(value) || Math.Abs(value) < double.Epsilon;
        }

        /// <summary>
        /// Safely compare doubles for eqaulity.
        /// </summary>
        /// <returns><c>true</c>, if equals was almosted, <c>false</c> otherwise.</returns>
        /// <param name="double1">Double1.</param>
        /// <param name="double2">Double2.</param>
        /// <param name="precision">Precision.</param>
        /// <remarks>
        /// Is it safe to check floating point values for equality to 0?:
        /// https://stackoverflow.com/a/485777</remarks>
        public static bool AlmostEquals(this double double1, double double2, double precision)
        {
            return (Math.Abs(double1 - double2) <= precision);
        }

    }
}