51 lines
1.8 KiB
C#
51 lines
1.8 KiB
C#
#nullable enable
|
|
|
|
using System;
|
|
|
|
namespace Demo2.Domain
|
|
{
|
|
public static class SaturatingMath
|
|
{
|
|
public const long Scale = 1000;
|
|
|
|
public static long Add(long left, long right)
|
|
{
|
|
if (right > 0 && left > long.MaxValue - right) return long.MaxValue;
|
|
if (right < 0 && left < long.MinValue - right) return long.MinValue;
|
|
return left + right;
|
|
}
|
|
|
|
public static long Multiply(long left, long right)
|
|
{
|
|
if (left == 0 || right == 0) return 0;
|
|
if (left == long.MinValue && right == -1) return long.MaxValue;
|
|
if (right == long.MinValue && left == -1) return long.MaxValue;
|
|
var negative = (left < 0) ^ (right < 0);
|
|
var a = AbsUnsigned(left);
|
|
var b = AbsUnsigned(right);
|
|
if (a > (ulong)long.MaxValue / b) return negative ? long.MinValue : long.MaxValue;
|
|
var value = (long)(a * b);
|
|
return negative ? -value : value;
|
|
}
|
|
|
|
public static long MultiplyScaled(long value, long multiplierMilli)
|
|
{
|
|
if (value == 0 || multiplierMilli == 0) return 0;
|
|
var product = Multiply(value, multiplierMilli);
|
|
if (product == long.MaxValue || product == long.MinValue) return product;
|
|
return product / Scale;
|
|
}
|
|
|
|
public static string Format(long value)
|
|
{
|
|
var abs = value == long.MinValue ? long.MaxValue : Math.Abs(value);
|
|
if (abs < 1_000_000_000) return value.ToString("N0");
|
|
var exponent = (int)Math.Floor(Math.Log10(abs));
|
|
var mantissa = value / Math.Pow(10, exponent);
|
|
return mantissa.ToString("0.##") + "e" + exponent;
|
|
}
|
|
|
|
private static ulong AbsUnsigned(long value) => value < 0 ? (ulong)(-(value + 1)) + 1UL : (ulong)value;
|
|
}
|
|
}
|