Search code examples
c#integerbit-manipulationdecimaldigit

How can I manipulate specific digits of an integer value?


I have to create a control that can manipulate each "digit" of an integer value ( from 0 to 999,999 ).

I know how to "Get" a digit of the integer - just Mod/Div -

public class IntegerModel{
    private int _value = 0;
    private int _GetValue( int baseValue, int modBy, int divBy ) => 
        ( baseValue % modBy ) / divBy;

    public int Value => _this.Value;

    public One => {
        get => this._GetValue( this.Value, 10, 1 );
        set => Console.WriteLine( "What do I put here?" );
    }

    public Ten{
        get => this._GetValue( this.Value, 100, 10 );
        set => Console.WriteLine( "What do I put here?" );
    }
}

The problem is that I don't know how to eloquently SET the digit value.

If I was working in Binary it would be as simple as using some bitwise operators ( it may still be but I don't know exactly how to do it ).

So, ideally, if I were to, using this class, do the following, I would get the given output.

IntegerModel Foo = new IntegerModel( );
Foo.One = 7;
Foo.Ten = 3;
Console.WriteLine( Foo.Value ); //Output should be 37

What would I need to put in the One and Ten property setters to be able to achieve the desired behavior?


Solution

  • I suggest modular arithmetics for both set and get; another suggestion is to implement indexer in order to access n-th digit of the integer.

      public class IntegerModel {
        private int _value = 0;
    
        private static int Power10(int value) {
          return (int) Math.Pow(10, value);
        }
    
        public int Value {
          get {
            return _value;
          }
        }
    
        //TODO: Implement ToString, Equals etc.
    
        public int this[int index] {
          get {
            if (index < 0 || index > 6)
              throw new ArgumentOutOfRangeException("index");
    
            return (_value / Power10(index)) % 10;  
          }
          set {
            if (index < 0 || index > 6)
              throw new ArgumentOutOfRangeException("index");
            else if (value < 0 || value > 9)
              throw new ArgumentOutOfRangeException("value");
    
            _value = (index / Power10(index + 1)) * Power10(index + 1) + 
                      value * Power10(index) +
                     _value % Power10(index);
          }
        }
      }
    

    If you insist on One, Ten etc. properties you can easily add them:

      public int One {
        get {return this[0];}    // 0th digit
        set {this[0] = value;}   // 0th digit
      }
    
      public int Ten {
        get {return this[1];}    // 1st digit
        set {this[1] = value;}   // 1st digit
      }
    
      public int Hundred {
        get {return this[2];}    // 2nd digit
        set {this[2] = value;}   // 2nd digit 
      }
    

    Test:

      IntegerModel test = new IntegerModel();
    
      // 987:
      test[0] = 7; // Last   (0th digit from the end)
      test[1] = 8; // Middle (1st digit from the end)
      test[2] = 9; // First  (2nd digit from the end)
    
      // 987
      Console.WriteLine(test.Value);