Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<pre><code>using System; public static class DecimalExtensions { public static int DigitAtPosition(this decimal number, int position) { if (position &lt;= 0) { throw new ArgumentException("Position must be positive."); } if (number &lt; 0) { number = Math.Abs(number); } number -= Math.Floor(number); if (number == 0) { return 0; } if (position == 1) { return (int)(number * 10); } return (number * 10).DigitAtPosition(position - 1); } } </code></pre> <p><strong>Edit</strong>: If you wish, you may separate the recursive call from the initial call, to remove the initial conditional checks during recursion:</p> <pre><code>using System; public static class DecimalExtensions { public static int DigitAtPosition(this decimal number, int position) { if (position &lt;= 0) { throw new ArgumentException("Position must be positive."); } if (number &lt; 0) { number = Math.Abs(number); } return number.digitAtPosition(position); } static int digitAtPosition(this decimal sanitizedNumber, int validPosition) { sanitizedNumber -= Math.Floor(sanitizedNumber); if (sanitizedNumber == 0) { return 0; } if (validPosition == 1) { return (int)(sanitizedNumber * 10); } return (sanitizedNumber * 10).digitAtPosition(validPosition - 1); } </code></pre> <hr> <p>Here's a few tests:</p> <pre><code>using System; using Xunit; public class DecimalExtensionsTests { // digit positions // 1234567890123456789012345678 const decimal number = .3216879846541681986310378765m; [Fact] public void Throws_ArgumentException_if_position_is_zero() { Assert.Throws&lt;ArgumentException&gt;(() =&gt; number.DigitAtPosition(0)); } [Fact] public void Throws_ArgumentException_if_position_is_negative() { Assert.Throws&lt;ArgumentException&gt;(() =&gt; number.DigitAtPosition(-5)); } [Fact] public void Works_for_1st_digit() { Assert.Equal(3, number.DigitAtPosition(1)); } [Fact] public void Works_for_28th_digit() { Assert.Equal(5, number.DigitAtPosition(28)); } [Fact] public void Works_for_negative_decimals() { const decimal negativeNumber = -number; Assert.Equal(5, negativeNumber.DigitAtPosition(28)); } [Fact] public void Returns_zero_for_whole_numbers() { const decimal wholeNumber = decimal.MaxValue; Assert.Equal(0, wholeNumber.DigitAtPosition(1)); } [Fact] public void Returns_zero_if_position_is_greater_than_the_number_of_decimal_digits() { Assert.Equal(0, number.DigitAtPosition(29)); } [Fact] public void Does_not_throw_if_number_is_max_decimal_value() { Assert.DoesNotThrow(() =&gt; decimal.MaxValue.DigitAtPosition(1)); } [Fact] public void Does_not_throw_if_number_is_min_decimal_value() { Assert.DoesNotThrow(() =&gt; decimal.MinValue.DigitAtPosition(1)); } [Fact] public void Does_not_throw_if_position_is_max_integer_value() { Assert.DoesNotThrow(() =&gt; number.DigitAtPosition(int.MaxValue)); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload