2

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?

Will
  • 3,413
  • 7
  • 50
  • 107
  • Can't you store array of digits, instead of one number? It would be much easier to manipulate with one digit. – Yurii N. Sep 25 '17 at 14:27

2 Answers2

3

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);
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • I like the look of this. I will try it out. – Will Sep 25 '17 at 14:39
  • Also, the reason for `One`, `Ten`, etc. is because the class is going to serve as a Model for an interface. – Will Sep 25 '17 at 14:50
  • @Will: interface with indexer seems to be a better choice; however, if the interface is fixed and you can't change it, well, `One` and `Ten` should be implemented. – Dmitry Bychenko Sep 25 '17 at 14:55
  • Problem is it has to support bi-directional binding. Well, it should in my MIND anyway... Interface hasn't been written yet. And you can't call `OnPropertyChanged` with an indexer. At least, you can't to my knowledge but that goes beyond the scope of this question. – Will Sep 25 '17 at 15:00
  • Tested. Works. Genius in simplicity. Here's your imaginary internet points. – Will Sep 25 '17 at 15:15
  • One thing - Setting the value works fine, getting it does not. I think that the error is in the return of the indexed getter - rather than saying `return ( index / ... )`, I think it should be saying `return ( this.Value / ... )` – Will Sep 25 '17 at 17:22
  • @Will: I am very sorry for the typo, `_value` for sure, not `index`. I've edited the answer. – Dmitry Bychenko Sep 25 '17 at 19:05
0

1 Split your overall value into three sections - high, low, relevant digit. Discard relevant digit...I just mentioned it to indicate the gap between "high" and "low"

2 To get hi, divide by something like (10^position + 1), then multiply by 10^(position + 1)

3 multiply relevant digit by (10^position)

4 add that to low (low should now be one digit longer)

5 Add high to low to get your final answer

My math is terrible, so expect a lot of off-by-one. I'm pretty sure the logic is sound, though.

theGleep
  • 1,179
  • 8
  • 14