diff --git a/Directory.Build.props b/Directory.Build.props
index 9ca331a..62f19cd 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,5 +1,8 @@
 
     
+        12.1.0
+        12.1.0
+        12.1.0
         net8.0;net9.0
         13
         enable
@@ -8,8 +11,5 @@
         en
         Copyright © ONIXLabs 2020
         https://github.com/onix-labs/onixlabs-dotnet
-        12.0.0
-        12.0.0
-        12.0.0
     
 
diff --git a/OnixLabs.Numerics.UnitTests/GenericMathPow10Tests.cs b/OnixLabs.Numerics.UnitTests/GenericMathPow10Tests.cs
new file mode 100644
index 0000000..09cb894
--- /dev/null
+++ b/OnixLabs.Numerics.UnitTests/GenericMathPow10Tests.cs
@@ -0,0 +1,94 @@
+// Copyright 2020-2025 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using Xunit;
+
+namespace OnixLabs.Numerics.UnitTests;
+
+public sealed class GenericMathPow10Tests
+{
+    [Theory(DisplayName = "GenericMath.Pow10 should produce the expected result (Int32)")]
+    [InlineData(0, 1)]
+    [InlineData(1, 10)]
+    [InlineData(2, 100)]
+    [InlineData(3, 1000)]
+    [InlineData(4, 10000)]
+    [InlineData(5, 100000)]
+    [InlineData(6, 1000000)]
+    [InlineData(9, 1000000000)]
+    public void GenericMathPow10ShouldProduceExpectedResultInt32(int exponent, int expected)
+    {
+        // Given / When
+        int result = GenericMath.Pow10(exponent);
+
+        // Then
+        Assert.Equal(expected, result);
+    }
+
+    [Theory(DisplayName = "GenericMath.Pow10 should produce the expected result (Int64)")]
+    [InlineData(0, 1L)]
+    [InlineData(1, 10L)]
+    [InlineData(2, 100L)]
+    [InlineData(10, 10000000000L)]
+    [InlineData(15, 1000000000000000L)]
+    public void GenericMathPow10ShouldProduceExpectedResultInt64(int exponent, long expected)
+    {
+        // Given / When
+        long result = GenericMath.Pow10(exponent);
+
+        // Then
+        Assert.Equal(expected, result);
+    }
+
+    [Theory(DisplayName = "GenericMath.Pow10 should produce the expected result (Double)")]
+    [InlineData(0, 1.0)]
+    [InlineData(3, 1000.0)]
+    [InlineData(6, 1e6)]
+    [InlineData(9, 1e9)]
+    [InlineData(15, 1e15)]
+    public void GenericMathPow10ShouldProduceExpectedResultDouble(int exponent, double expected)
+    {
+        // Given / When
+        double result = GenericMath.Pow10(exponent);
+
+        // Then
+        Assert.Equal(expected, result, precision: 10);
+    }
+
+    [Theory(DisplayName = "GenericMath.Pow10 should produce the expected result (Decimal)")]
+    [InlineData(0, "1")]
+    [InlineData(1, "10")]
+    [InlineData(5, "100000")]
+    [InlineData(10, "10000000000")]
+    public void GenericMathPow10ShouldProduceExpectedResultDecimal(int exponent, string expectedStr)
+    {
+        // Given / When
+        decimal expected = decimal.Parse(expectedStr);
+        decimal result = GenericMath.Pow10(exponent);
+
+        // Then
+        Assert.Equal(expected, result);
+    }
+
+    [Fact(DisplayName = "GenericMath.Pow10 should throw ArgumentException when the exponent is negative.")]
+    public void GenericMathPow10ShouldThrowArgumentExceptionWhenExponentNegative()
+    {
+        // Given / When
+        Exception exception = Assert.Throws(() => GenericMath.Pow10(-1));
+
+        // Then
+        Assert.Contains("Exponent must be greater", exception.Message);
+    }
+}
diff --git a/OnixLabs.Numerics.UnitTests/NumericsExtensionsTests.cs b/OnixLabs.Numerics.UnitTests/NumericsExtensionsTests.cs
index 4fc4ee4..3d408c0 100644
--- a/OnixLabs.Numerics.UnitTests/NumericsExtensionsTests.cs
+++ b/OnixLabs.Numerics.UnitTests/NumericsExtensionsTests.cs
@@ -80,6 +80,107 @@ public void DecimalGetUnscaledValueShouldProduceExpectedResultValueAndScale(int
         Assert.Equal(expected, actual);
     }
 
+    [Theory(DisplayName = "Decimal.SetScale should preserve or pad when scale is less or equal")]
+    [InlineData("123.0", 2, "123.00")]
+    [InlineData("123.00", 2, "123.00")]
+    [InlineData("123.000", 2, "123.00")]
+    [InlineData("0.0", 2, "0.00")]
+    [InlineData("123.12", 2, "123.12")]
+    public void DecimalSetScaleShouldPreserveOrPadWhenScaleIsLessOrEqual(string inputStr, int scale, string expectedStr)
+    {
+        // Given
+        decimal input = decimal.Parse(inputStr);
+        decimal expected = decimal.Parse(expectedStr);
+
+        // When
+        decimal result = input.SetScale(scale);
+
+        // Then
+        Assert.Equal(expected, result);
+    }
+
+    [Theory(DisplayName = "Decimal.SetScale should truncate when no precision loss")]
+    [InlineData("123.1200", 2, "123.12")]
+    [InlineData("0.1000", 1, "0.1")]
+    [InlineData("999.0000", 3, "999.000")]
+    public void DecimalSetScaleShouldTruncateWhenNoPrecisionLoss(string inputStr, int scale, string expectedStr)
+    {
+        // Given
+        decimal input = decimal.Parse(inputStr);
+        decimal expected = decimal.Parse(expectedStr);
+
+        // When
+        decimal result = input.SetScale(scale);
+
+        // Then
+        Assert.Equal(expected, result);
+    }
+
+    [Theory(DisplayName = "Decimal.SetScale should throw when truncation would lose precision")]
+    [InlineData("123.456", 2)]
+    [InlineData("1.001", 2)]
+    [InlineData("0.123456789", 5)]
+    public void DecimalSetScaleShouldThrowWhenTruncationWouldLosePrecision(string inputStr, int scale)
+    {
+        // Given
+        decimal input = decimal.Parse(inputStr);
+
+        // When / Then
+        Assert.Throws(() => input.SetScale(scale));
+    }
+
+    [Theory(DisplayName = "Decimal.SetScale(rounding) should apply correct rounding")]
+    [InlineData("123.456", 2, MidpointRounding.AwayFromZero, "123.46")]
+    [InlineData("123.454", 2, MidpointRounding.AwayFromZero, "123.45")]
+    [InlineData("123.455", 2, MidpointRounding.ToZero, "123.45")]
+    [InlineData("123.455", 2, MidpointRounding.ToEven, "123.46")]
+    [InlineData("0.125", 2, MidpointRounding.ToEven, "0.12")]
+    [InlineData("0.135", 2, MidpointRounding.ToEven, "0.14")]
+    public void DecimalSetScaleWithRoundingShouldApplyCorrectRounding(string inputStr, int scale, MidpointRounding mode, string expectedStr)
+    {
+        // Given
+        decimal input = decimal.Parse(inputStr);
+        decimal expected = decimal.Parse(expectedStr);
+
+        // When
+        decimal result = input.SetScale(scale, mode);
+
+        // Then
+        Assert.Equal(expected, result);
+    }
+
+    [Theory(DisplayName = "Decimal.SetScale(rounding) should truncate when no precision loss")]
+    [InlineData("123.0000", 2, MidpointRounding.AwayFromZero, "123.00")]
+    [InlineData("1.000", 1, MidpointRounding.ToEven, "1.0")]
+    public void DecimalSetScaleWithRoundingShouldTruncateWhenNoPrecisionLoss(string inputStr, int scale, MidpointRounding mode, string expectedStr)
+    {
+        // Given
+        decimal input = decimal.Parse(inputStr);
+        decimal expected = decimal.Parse(expectedStr);
+
+        // When
+        decimal result = input.SetScale(scale, mode);
+
+        // Then
+        Assert.Equal(expected, result);
+    }
+
+    [Fact(DisplayName = "Decimal.SetScale should throw when scale is negative")]
+    public void DecimalSetScaleShouldThrowWhenScaleIsNegative()
+    {
+        // Given / When / Then
+        Exception exception = Assert.Throws(() => 123.45m.SetScale(-1));
+        Assert.Contains("Scale must be greater than, or equal to zero.", exception.Message);
+    }
+
+    [Fact(DisplayName = "Decimal.SetScale(rounding) should throw when scale is negative")]
+    public void DecimalSetScaleWithRoundingShouldThrowWhenScaleIsNegative()
+    {
+        // Given / When / Then
+        Exception exception = Assert.Throws(() => 123.45m.SetScale(-1, MidpointRounding.AwayFromZero));
+        Assert.Contains("Scale must be greater than, or equal to zero.", exception.Message);
+    }
+
     [Theory(DisplayName = "INumber.IsBetween should produce the expected result")]
     [InlineData(0, 0, 0, true)]
     [InlineData(0, 0, 1, true)]
diff --git a/OnixLabs.Numerics/GenericMath.cs b/OnixLabs.Numerics/GenericMath.cs
index cd25140..25971b4 100644
--- a/OnixLabs.Numerics/GenericMath.cs
+++ b/OnixLabs.Numerics/GenericMath.cs
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+using System;
 using System.Globalization;
 using System.Numerics;
 
@@ -41,7 +42,7 @@ public static BigInteger Factorial(T value) where T : IBinaryInteger
     {
         Require(value >= T.Zero, "Value must be greater than or equal to zero.");
 
-        if(value <= T.One) return BigInteger.One;
+        if (value <= T.One) return BigInteger.One;
 
         BigInteger result = BigInteger.One;
 
@@ -71,4 +72,33 @@ public static int IntegerLength(T value) where T : INumberBase
     /// The underlying  type.
     /// Returns the minimum and maximum values from the specified left-hand and right-hand values.
     public static (T Min, T Max) MinMax(T left, T right) where T : INumber => (T.Min(left, right), T.Max(left, right));
+
+    /// 
+    /// Computes 10 raised to the power of a non-negative integer exponent using exponentiation by squaring, for any numeric type implementing .
+    /// 
+    /// The numeric type. Must implement .
+    /// The exponent to raise 10 to. Must be greater than or equal to zero.
+    /// A value of type  equal to 10 raised to the power of .
+    ///  if  is less than zero.
+    public static T Pow10(int exponent) where T : INumber
+    {
+        Require(exponent >= 0, "Exponent must be greater than, or equal to zero.", nameof(exponent));
+
+        if (exponent == 0)
+            return T.One;
+
+        T result = T.One;
+        T baseValue = T.CreateChecked(10);
+
+        while (exponent > 0)
+        {
+            if ((exponent & 1) == 1)
+                result *= baseValue;
+
+            baseValue *= baseValue;
+            exponent >>= 1;
+        }
+
+        return result;
+    }
 }
diff --git a/OnixLabs.Numerics/NumericsExtensions.cs b/OnixLabs.Numerics/NumericsExtensions.cs
index 3b9f94f..46435c0 100644
--- a/OnixLabs.Numerics/NumericsExtensions.cs
+++ b/OnixLabs.Numerics/NumericsExtensions.cs
@@ -51,6 +51,73 @@ public static BigInteger GetUnscaledValue(this decimal value)
         return decimal.IsPositive(value) ? result : -result;
     }
 
+    /// 
+    /// Sets the scale (number of digits after the decimal point) of the current  value.
+    /// 
+    /// If the scale of the current  value is less than the specified scale, then the scale will be padded with zeroes.
+    /// If the scale of the current  value is greater that the specified scale, then the scale will be truncated,
+    /// provided that there is no loss of precision; otherwise,  will be thrown.
+    /// 
+    /// 
+    /// The decimal value to adjust.
+    /// The desired, non-negative scale.
+    /// A new  with the exact specified scale.
+    ///  if reducing the scale would result in a loss of precision.
+    ///  if  is negative.
+    public static decimal SetScale(this decimal value, int scale)
+    {
+        Require(scale >= 0, "Scale must be greater than, or equal to zero.", nameof(scale));
+
+        if (value.Scale == scale)
+            return value;
+
+        if (value.Scale < scale)
+        {
+            decimal factor = GenericMath.Pow10(scale - value.Scale);
+            return value * factor / factor;
+        }
+
+        decimal pow10 = GenericMath.Pow10(scale);
+        decimal truncated = Math.Truncate(value * pow10) / pow10;
+
+        if (value == truncated)
+            return truncated;
+
+        throw new InvalidOperationException($"Cannot reduce scale without losing precision: {value}");
+    }
+
+    /// 
+    /// Sets the scale (number of digits after the decimal point) of the current  value.
+    /// 
+    /// If the scale of the current  value is less than the specified scale, then the scale will be padded with zeroes.
+    /// If the scale of the current  value is greater that the specified scale, then the scale will be truncated,
+    /// provided that there is no loss of precision; otherwise, the value is rounded using the specified  mode.
+    /// 
+    /// 
+    /// The decimal value to adjust.
+    /// The desired scale (number of decimal digits). Must be non-negative.
+    /// The rounding strategy to apply if the scale must be reduced with precision loss.
+    /// A new  with the exact specified scale.
+    ///  if  is negative.
+    public static decimal SetScale(this decimal value, int scale, MidpointRounding mode)
+    {
+        Require(scale >= 0, "Scale must be greater than, or equal to zero.", nameof(scale));
+
+        if (value.Scale == scale)
+            return value;
+
+        if (value.Scale < scale)
+        {
+            decimal factor = GenericMath.Pow10(scale - value.Scale);
+            return value * factor / factor;
+        }
+
+        decimal pow10 = GenericMath.Pow10(scale);
+        decimal truncated = Math.Truncate(value * pow10) / pow10;
+
+        return value == truncated ? truncated : Math.Round(value, scale, mode);
+    }
+
     /// 
     /// Gets the current value as an unscaled integer.
     /// 
diff --git a/OnixLabs.Playground/Program.cs b/OnixLabs.Playground/Program.cs
index d629839..c03417f 100644
--- a/OnixLabs.Playground/Program.cs
+++ b/OnixLabs.Playground/Program.cs
@@ -12,11 +12,64 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+using System;
+
 namespace OnixLabs.Playground;
 
 internal static class Program
 {
     private static void Main()
     {
+        decimal value = 100.13m;
+        decimal round = value.SetScale(2);
+
+        Console.WriteLine(round);
+    }
+
+    public static decimal SetScale(this decimal value, int scale)
+    {
+        Require(scale >= 0, "Scale must be greater than, or equal to zero.");
+
+        // Count actual decimal places
+        int actualScale = GetDecimalPlaces(value);
+
+        if (actualScale == scale)
+        {
+            return value;
+        }
+
+        if (actualScale < scale)
+        {
+            // Pad with zeroes by scaling and descaling
+            decimal factor = Pow10(scale - actualScale);
+            return value * factor / factor;
+        }
+
+        else // actualScale > scale
+        {
+            // Check if the digits beyond the desired scale are zero
+            decimal factor = Pow10(actualScale - scale);
+            decimal remainder = (value * factor) % 1;
+
+            if (remainder != 0)
+                throw new InvalidOperationException($"Cannot reduce scale without losing precision: {value}");
+
+            return Math.Truncate(value * Pow10(scale)) / Pow10(scale);
+        }
+    }
+
+    private static int GetDecimalPlaces(decimal value)
+    {
+        int[] bits = decimal.GetBits(value);
+        byte scale = (byte)((bits[3] >> 16) & 0x7F);
+        return scale;
+    }
+
+    private static decimal Pow10(int exp)
+    {
+        decimal result = 1m;
+        for (int i = 0; i < exp; i++)
+            result *= 10;
+        return result;
     }
 }