How to add a second argument(Number) to a calculator program? - c#

I'm working on a small calculator program in Unity.
I only need the calculator to work with two numbers.
The feature I'm trying to implement:
After inputting the math operator, It should display the second number in the third index.
The issue:
Instead of Adding a second number, the first number is being overwritten if a different number is pressed on the keyboard.
Here's the script I've created:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Functions : MonoBehaviour
{
// Global Variable to display text on top panel
public Text panelText;
// Create a number variable
string num;
string num1;
string num2;
string mOpr;
string calNum;
string cbutton;
string opr;
bool isFirstNum;
// Start is called before the first frame update
void Start()
{
}
// A function with an int argument
public void NumberInputOne(string num)
{
num1 = num;
num2 = num;
if (panelText.text.Length < 1)
{
Debug.Log(num1);
panelText.text = num1;
isFirstNum = false;
}
else if (panelText.text.Length > 1 && panelText.text.Length < 3)
{
num2 = num;
Debug.Log(num2);
panelText.text = num1 + mOpr + num2;
}
}
public void OperatorInput(string opr)
{
mOpr = opr;
if (panelText.text.Length > 0 && panelText.text.Length < 2)
{
panelText.text = num1 + mOpr;
}
}
// public void NumberInputTwo(int num)
//{
// ResNum2 = num;
// Debug.Log(ResNum2);
// if (panelText.text.Length > 1 && panelText.text.Length < 3)
// {
// panelText.text = ResNum1 + opr + ResNum2;
// }
// }
public void RestartCal(string cButton)
{
panelText.text = "";
}
}
I've also added a screen recording to capture the issue:
First number being overwritten
Do you have any suggestions?
Thank you

use the NumberInputOne func like below;
public void NumberInputOne(string num)
{
if (num1 is null)
{
Debug.Log(num1);
panelText.text = num1;
num1 = num
}
else
{
num2 = num;
Debug.Log(num2);
panelText.text = num1 + mOpr + num2;
}
}
btw i recommend that you review the sample calculation application codes. because apart from what you're asking, there are places you need to improve in general.

This feels like a beginner programming exercise. But the right way to build a calculator involves programming concepts that you probably haven't been taught yet. Which makes this a poor choice as an assignment.
Personally I would build a calculator by defining a simple syntax tree to represent the formula being input. Including methods to display the formula and calculate the answer. For example;
public interface IValue
{
int Calculate();
string PrintValue();
}
public class Number : IValue
{
public int? Value;
public void AddDigit(int digit) => Value = (Value ?? 0) * 10 + digit;
public int Calculate() => Value ?? 0;
public string PrintValue() => Value?.ToString();
}
public abstract class BinaryOperator : IValue
{
public IValue Left;
public IValue Right;
public abstract int Operation(int left, int right);
public abstract char Operator { get; }
public int Calculate()
{
var left = Left.Calculate();
var right = Right.Calculate();
return Operation(left, right);
}
public string PrintValue() => $"{Left?.PrintValue()} {Operator} {Right?.PrintValue()}";
}
public class Addition : BinaryOperator
{
public override char Operator => '+';
public override int Operation(int left, int right) => left + right;
}
// TODO define other operators
Then think about how each button should change the syntax tree.
// the entire formula
public IValue Root;
// the number currently being typed
public Number Input;
public void Display() {
panelText.text = Root.PrintValue();
}
// start / clear
public void Start(){
Root = Input = new Number(){
Value = 0
};
Display();
}
public void Plus(){
// left as an exercise for the reader
Display();
}
public void Digit(int digit) {
Input.AddDigit(digit);
Display();
}
public void Calculate() {
// left as an exercise for the reader
Display();
}

Related

Variable Values are not getting Updated

I have 3 class files. First is the Main class, second is the Ship class, and the third is the Skill class. All values are added to my Main class file. I have a method where the parameters should be the value in my Main class. Please see below:
public class Skill
{
public double _capInc;
public int bscEng, advEng, expEng;
// engineering
public double capInc(int bsc, int adv, int exp)
{
if(bsc == 5 && adv == 5 && exp == 4)
{
_capInc = 0.48;
}
return _capInc;
}
The values of int bsc, int adv, and int exp should be the value of bscEng, advEng, & expEng which was set in my Main class
skill.bscEng = 5;
skill.advEng = 5;
skill.expEng = 4;
But when I try to run the method in my Ship class, values are different
public class Ship
{
Skill skill = new Skill();
public double capacitor;
public double totalCap()
{
double _totalCap = capacitor * skill.capInc(skill.bscEng, skill.advEng, skill.expEng);
Console.WriteLine(skill.bscEng + " bscEng inside totalCap");
return _totalCap;
}
This is the result when I run my Main class
class MainClass
{
public static void Main (string[] args)
{
Ship ship = new Ship();
Skill skill = new Skill();
skill.bscEng = 5;
skill.advEng = 5;
skill.expEng = 4;
Console.WriteLine(skill.bscEng + " bscEng in Main");
Console.WriteLine(ship.totalCap());
}
}
Result:
5 bscEng in Main
0 bscEg inside totalCap
0
You should assign the values to skill in your ship object.
Example:
ship.skill.bscEng = <yourValue>;
ship.skill.advEng = <yourValue>;
ship.skill.expEng = <yourValue>;
As I said in the comments you need to pass the skill object to the ship object. I've also added an constructor to both classes. I don't know what you really want to do and the code is weird but here's a working solution:
class MainClass
{
public static void Main (string[] args)
{
Skill skill = new Skill(5, 5, 4);
Ship ship = new Ship(skill);
Console.WriteLine(skill.bscEng + " bscEng in Main");
Console.WriteLine(ship.totalCap());
}
}
public class Skill
{
public Skill(int bscEnd, int advEng, int expEng)
{
this.bscEng = bscEnd;
this.advEng = advEng;
this.expEng = expEng;
}
public double _capInc;
public int bscEng, advEng, expEng;
// engineering
public double capInc()
{
if(bscEng == 5 && advEng == 5 && expEng == 4)
{
_capInc = 0.48;
}
return _capInc;
}
}
public class Ship
{
public Ship(Skill skill)
{
Skill = skill;
capacitor = 1.0; // TODO
}
private Skill Skill;
public double capacitor;
public double totalCap()
{
double _totalCap = capacitor * Skill.capInc();
Console.WriteLine(Skill.bscEng + " bscEng inside totalCap");
return _totalCap;
}
}
Output should be:
5 bscEng in Main
5 bscEng inside totalCap
0,48

C# Compound Interest Calculator Using a Loop (Error CS0103)

I want to create a Compound Interest Calculator in C# using two classes in different namespaces but can't for the life of me figure out why I keep getting errors.
PSA I am a beginner, I know this code probably looks awful, but please be kind.
Here is CompoundTest.cs
namespace CompoundTest
{
class Program
{
static void Main(string[] args)
{
CompoundClass newprogram = new CompoundClass();
Console.Write("\nPlease enter the initial balance for your account: ");
double balance = Convert.ToDouble(Console.ReadLine());
Console.Write("\nPlease enter the annual interest rate: ");
double interestRate = Convert.ToDouble(Console.ReadLine()) / 100;
Console.Write("\nHow many years will you acrue interest? ");
double annualAmount = Convert.ToDouble(Console.ReadLine());
Console.WriteLine($"Your balance after {annualAmount} years is {accountBalance:C}");
Console.ReadLine();
}
}
}
And here is Compound.cs
using System;
namespace Compound
{
public class CompoundClass
{
private double balance;
public int value { get; private set; }
public CompoundClass()
{
Balance = value;
}
public double Balance
{
get
{
return balance;
}
private set
{
if (value > 0)
{
balance = value;
}
}
}
public void Rate(double interestRate)
{
interestRate = value / 100;
}
public void Years(double annualAmount)
{
annualAmount = value * 12;
}
public void addMethod(double accountBalance)
{
for (int i = 1; i < annualAmount + 1; i++)
{
accountBalance = balance * Math.Pow(1 + interestRate / annualAmount, annualAmount * i);
}
}
}
}
I get the error:
CS0103 C# The name '..' does not exist in the current context - in the public void addMethod(double accountBalance) method
You are not storing any data on the CompoundClass, the method
public void Rate(double interestRate)
{
interestRate = value / 100;
}
only operates on the input parameter interestrate inside the functions scope, after that the result of the calculation is lost
If you want to reuse a variable on the entire lifetime of the CompoundClass, then define it as a member variable like:
private double _interestRate
and change your function to
public void Rate()
{
_interestRate = value / 100;
}
and for the annualAmount as well
private double _annualAmount;
public void Years()
{
_annualAmount = value * 12;
}
and your calculation to
public double addMethod(double accountBalance)
{
for (int i = 1; i < annualAmount + 1; i++)
{
accountBalance = balance * Math.Pow(1 + _interestRate / _annualAmount, _annualAmount * i);
}
return accountBalance;
}
There is more then one thing wrong with this code. And I am honestly not sure if I even got anything close to your problem yet.
using System;
namespace Compound
{
public class CompoundClass
{
private double balance;
public int value { get; private set; }
public CompoundClass()
{
//Balance with a big B is nowhere in context
Balance = value;
}
public double Balance
{
get
{
return balance;
}
private set
{
if (value > 0)
{
balance = value;
}
}
}
//As remarked by somebody else, this function does nothing. Without return or out parameter, interest rate will stay at nothing.
public void Rate(double interestRate)
{
interestRate = value / 100;
}
//The naming of this variable is bad. Did you mean "Amoung of Months"?
//Also as someone else pointed out, you do not return or otherwise persist this value
public void Years(double annualAmount)
{
annualAmount = value * 12;
}
//Method does not return anything.
//accountBalance is a local value and will not persist
public void addMethod(double accountBalance)
{
for (int i = 1; i < annualAmount + 1; i++)
{
//Avoid putting that much stuff into 1 line. It really messes with your ability to debug
//1-2 operations + 1 assignment to a temporary variable per line
//Anything more and you will have serious issues debugging this
accountBalance = balance * Math.Pow(1 + interestRate / annualAmount, annualAmount * i);
}
}
}
}
Generally the variables this works with should be either purely parameters (wich means it should be a static class with static functions) or mostly class variables. You have both things mixed all over the place.

C# Comparing List objects to passed parameters

What I am trying to do is get the number of right angled triangles between 1 and 20 on both sides.
Most of the logic is fine, but when I want to check for 3, 4 and 5 this is one triangle, while 4, 3 and 5 would not be valid as it 3, 4, 5 in a different order.
Here is the code that I have written for the problem area
public bool isAlreadyValidTriangle(int intAdj, int intOpp, List<Triangle> triangleList)
{
bool breakLoop = false;
Int32 length = triangleList.Count;
for (int index = 0; index < length && breakLoop != false; index++)
{
//This is to compare an existing adjacent that is stored in the list to the
//supplied opposite, this is to prebent the 3, 4, 5 and 4, 3, 5 issue
var response = triangleList.Find(r => r.IntAdjacent == intOpp);
if (response !=null)
{
//This is to compare an existing opposite that is stored in the list to the
//supplied adjacent, this is to prebent the 3, 4, 5 and 4, 3, 5 issue
var otherResponse = triangleList.Find(r => r.IntOpposite == intAdj);
if (otherResponse != null)
{
breakLoop = true;
}
}
}
return breakLoop;
}
Just in case anybody needs the Triangle code, here it is
public class Triangle
{
private int intAdjacent;
private int intOpposite;
private int intHypotenuse;
public Triangle(int intAdjacent, int intOpposite, int intHypotenuse)
{
this.intAdjacent = intAdjacent;
this.intOpposite = intOpposite;
this.intHypotenuse = intHypotenuse;
}
public int IntAdjacent
{
get { return intAdjacent; }
}
public int IntOpposite
{
get { return intOpposite; }
}
public int IntHypotenuse
{
get { return intHypotenuse; }
}
}
Could some one spot to see where I am making a mistake in the logic or have made an error in the code itself?
Keith
You can simplify this quite a lot like this:
public bool isAlreadyValidTriangle(int intAdj, int intOpp, List<Triangle> triangleList)
{
if(triangleList.Any(t => t.IntAdjacent == intAdj && t.IntOpposite == intOpp))
return true;
return triangleList.Any(t => t.IntAdjacent == intOpp && t.IntOpposite == intAdj);
}
It first looks for any matches where the passed in values are a match, then reverses the search if they don't. It's slightly different to your code in that it looks for both adjacent and opposite at the same time which is where you went wrong. Additionally, it uses Any which returns a boolean value if any item is found that matches.
Thinking about this further, I would change the function to make it an extension method like this:
public static bool isAlreadyValidTriangle(this List<Triangle> triangleList, int intAdj, int intOpp)
{
if(triangleList.Any(t => t.IntAdjacent == intAdj && t.IntOpposite == intOpp))
return true;
return triangleList.Any(t => t.IntAdjacent == intOpp && t.IntOpposite == intAdj);
}
This means you can call it with a little more readability:
List<Triangle> triangleList = new List<Triangle>();
... fill list with triangles ...
if(triangleList.isAlreadyValidTriangle(adjacent, opposite)
{
...
}
First of all thanks for the advice and help.
Here is the complete code from start to finish
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace ConsoleApplication1
{
public class Program
{
private static double doubleHypotenuse = 0;
private static int adjacent = 1;
private static int opposite = 1;
private static int limit = 200;
private static int count = 0;
public static void Main(string[] args)
{
TriangleLogic triLogic = new TriangleLogic();
List<Triangle> triangleList = new List<Triangle>();
List<Triangle> trianglePlus1 = new List<Triangle>();
while (adjacent < limit)
{
opposite = 1;
while (opposite < limit)
{
doubleHypotenuse = triLogic.intRightAngle(adjacent, opposite);
if (doubleHypotenuse % 1 == 0)
{
if (!triLogic.isAlreadyValidTriangle(adjacent, opposite, triangleList))
{
triangleList.Add(new Triangle(adjacent, opposite, (int)Convert.ToInt32(doubleHypotenuse)));
}
count++;
}
opposite++;
}
adjacent++;
}
Console.WriteLine("The following are integer triangles");
triangleList.ForEach(delegate(Triangle pytag)
{
if ((pytag.IntHypotenuse - pytag.IntOpposite) == 1)
{
trianglePlus1.Add(new Triangle(pytag.IntAdjacent, pytag.IntOpposite, pytag.IntHypotenuse));
}
Console.WriteLine(pytag.IntAdjacent + ", " + pytag.IntOpposite + " and " + pytag.IntHypotenuse);
});
Console.WriteLine("the number of squares is " + count);
Int32 length = triangleList.Count;
Console.WriteLine("the length of the list is " + length);
Console.WriteLine("");
Console.WriteLine("the List of triangles with the hypotenuse 1 ");
Console.WriteLine("more than the opposite");
trianglePlus1.ForEach(delegate(Triangle pytagPlus1)
{
Console.WriteLine(pytagPlus1.IntAdjacent + ", " + pytagPlus1.IntOpposite + " and " + pytagPlus1.IntHypotenuse);
});
Int32 lengthPlus1 = trianglePlus1.Count;
Console.WriteLine("the length of the list is " + lengthPlus1);
}
}
}
Here is the Triangle Class
public class Triangle
{
private int intAdjacent;
private int intOpposite;
private int intHypotenuse;
public Triangle(int intAdjacent, int intOpposite, int intHypotenuse)
{
this.intAdjacent = intAdjacent;
this.intOpposite = intOpposite;
this.intHypotenuse = intHypotenuse;
}
public int IntAdjacent
{
get { return intAdjacent; }
}
public int IntOpposite
{
get { return intOpposite; }
}
public int IntHypotenuse
{
get { return intHypotenuse; }
}
}
And finally the TriangleLogic class
public class TriangleLogic
{
private double squareAdjacent = 0;
private double squareOpposite = 0;
private double squareSum = 0;
public TriangleLogic()
{
}
public double intRightAngle(int intAdjacent, int intOpposite)
{
squareAdjacent = Math.Pow(Convert.ToDouble(intAdjacent), 2);
squareOpposite = Math.Pow(Convert.ToDouble(intOpposite), 2);
squareSum = squareAdjacent + squareOpposite;
return Math.Sqrt(squareSum);
}
public bool isAlreadyValidTriangle(int intAdj, int intOpp, List<Triangle> triangleList)
{
if (triangleList.Any(t => t.IntAdjacent == intAdj && t.IntOpposite == intOpp))
return true;
return triangleList.Any(t => t.IntAdjacent == intOpp && t.IntOpposite == intAdj);
}
}
Thanks again for the support

Using multiple classes

I am trying to make a simple program that asks the user to enter an integer. Once the program receives the input it takes and stores it and then counts from 1 to the input integer and sums the total of the count. Then it displays the results in a meaningful way to the user and prompts them if they would like to process another number. The point of this program is to use loops and multiple classes. I know that I am really close to the desired end product but cannot figure out why the AccumulateValue() method is not working properly. It does not seem to be going into the conditional while statement that I made. If anyone could give me some insight to my problem that would be great!
Here is my code:
AccumulatorApp.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Project
{
class AccumulatorApp
{
static void Main(string[] args)
{
string loopControl = "Y";
int sum;
int enteredValue;
DisplayTitle();
while (loopControl == "Y" || loopControl == "YES")
{
enteredValue = InputInteger(0);
Accumulator number = new Accumulator(enteredValue);
sum = number.AccumulateValues();
DisplayOutput(sum, enteredValue);
Console.Write("\tWould you like to process another number? \n\t\t<Y or N>: ");
loopControl = Console.ReadLine().ToUpper();
}
}
public static void DisplayTitle()
{
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
Console.Clear();
Console.WriteLine();
Console.WriteLine("\tProgramming Assignment 05 - Accumulator - Robert");
DrawLine();
}
public static int InputInteger(int enteredValue)
{
Console.Write("\tPlease enter a positive integer: ");
enteredValue = Convert.ToInt32(Console.ReadLine());
if (enteredValue > 0)
{
return enteredValue;
}
else
{
Console.WriteLine("\tInvalid input. Please enter a POSITIVE integer: ");
enteredValue = Convert.ToInt32(Console.ReadLine());
}
return enteredValue;
/*
Console.Write("Please enter a positive integer: ");
int enteredValue = Convert.ToInt32(Console.ReadLine());
return enteredValue;
* */
}
public static void DisplayOutput(int sum, int inputValue)
{
Console.WriteLine("\tThe inputed integer is: {0}", inputValue);
Console.WriteLine("\tThe sum of 1 through {0} = {1}", inputValue, sum);
DrawLine();
}
public static void DrawLine()
{
Console.WriteLine("\t______________________________________________________");
Console.WriteLine();
}
}
}
Accumulator.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Project
{
class Accumulator
{
int integerEntered;
public Accumulator()
{
}
public Accumulator(int integerEntered)
{
int enteredInteger = integerEntered;
}
public int AccumulateValues()
{
int accumulatedValue = 0;
int counterValue = 1;
while (counterValue <= integerEntered)
{
Console.WriteLine("\tPasses through loop = {0}", accumulatedValue);
accumulatedValue = accumulatedValue + counterValue;
counterValue = counterValue + 1;
}
return accumulatedValue;
}
}
}
When you are instantiating a new instance of Accumulator through it's constructor containing one int argument you were setting the passed value equal to the field within the class (Setting them both to 0.)
Your accumulator class should look like this:
class Accumulator
{
int integerEntered;
public Accumulator()
{
}
public Accumulator(int passedInteger)
{
//Local field is equal to passedInteger, not the other way around.
integerEntered = passedInteger;
}
public int AccumulateValues()
{
int accumulatedValue = 0;
int counterValue = 1;
while (counterValue <= integerEntered)
{
Console.WriteLine("\tPasses through loop = {0}", accumulatedValue);
accumulatedValue = accumulatedValue + counterValue;
//Increment does the same thing you were doing
counterValue++;
}
return accumulatedValue;
}
}
It looks like the problem may actually be with your value constructor. When this line is called:
Accumulator number = new Accumulator(enteredValue);
A new Accumulator is being made with your value constructor:
public Accumulator(int integerEntered)
{
int enteredInteger = integerEntered;
}
The problem is that integerEntered isn't really saved anywhere and once enteredInteger goes out of scope (end of constructor), the value that was entered is essentially lost as far as the Accumulator object is concerned. I think what you want is:
public Accumulator(int integerEntered)
{
integerEntered = integerEntered;
}
As a heads up, you may have to do this.integerEntered = integerEntered;
Also I think you want to subtract 1 from integerEntered each iteration of your while loop in AccumulateValues().
There 2 -3 things needs to be changed
1) you are not assigning values to integerEntered in your constructor so I have changed it
2) you should integerEntered as a property so i have changed it to public int integerEntered { get; set; }
3) the logic of calculating to count AccumulateValues .. actually mathematical formula is the sum up to integer n is = (n * (n+1))/2 so i have changed it too
try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Project
{
class Accumulator
{
public int integerEntered { get; set; }
public Accumulator()
{
}
public Accumulator(int integerPassed)
{
integerEntered = integerPassed;
}
public int AccumulateValues()
{
int accumulatedValue = 0;
if(integerEntered > 0)
{
accumulatedValue = (integerEntered * (integerEntered + 1))/2;
}
return accumulatedValue;
}
}
}

What is the best way to find the digit at n position in a decimal number?

Background
I'm working on a symmetric rounding class and I find that I'm stuck with regards to how to best find the number at position x that I will be rounding. I'm sure there is an efficient mathematical way to find the single digit and return it without having to resort to string parsing.
Problem
Suppose, I have the following (C#) psuedo-code:
var position = 3;
var value = 102.43587m;
// I want this no ↑ (that is 5)
protected static int FindNDigit(decimal value, int position)
{
// This snippet is what I am searching for
}
Also, it is worth noting that if my value is a whole number, I will need to return a zero for the result of FindNDigit.
Does anyone have any hints on how I should approach this problem? Is this something that is blaringly obvious that I'm missing?
(int)(value * Math.Pow(10, position)) % 10
How about:
(int)(double(value) * Math.Pow(10, position)) % 10
Basically you multiply by 10 ^ pos in order to move that digit to the one's place, and then you use the modulus operator % to divide out the rest of the number.
using System;
public static class DecimalExtensions
{
public static int DigitAtPosition(this decimal number, int position)
{
if (position <= 0)
{
throw new ArgumentException("Position must be positive.");
}
if (number < 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);
}
}
Edit:
If you wish, you may separate the recursive call from the initial call, to remove the initial conditional checks during recursion:
using System;
public static class DecimalExtensions
{
public static int DigitAtPosition(this decimal number, int position)
{
if (position <= 0)
{
throw new ArgumentException("Position must be positive.");
}
if (number < 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);
}
Here's a few tests:
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<ArgumentException>(() => number.DigitAtPosition(0));
}
[Fact]
public void Throws_ArgumentException_if_position_is_negative()
{
Assert.Throws<ArgumentException>(() => 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(() => decimal.MaxValue.DigitAtPosition(1));
}
[Fact]
public void Does_not_throw_if_number_is_min_decimal_value()
{
Assert.DoesNotThrow(() => decimal.MinValue.DigitAtPosition(1));
}
[Fact]
public void Does_not_throw_if_position_is_max_integer_value()
{
Assert.DoesNotThrow(() => number.DigitAtPosition(int.MaxValue));
}
}
Edited: Totally had the wrong and opposite answer here. I was calculating the position to the left of the decimal instead of the right. See the upvoted answers for the correct code.
I found this one here working:
public int ValueAtPosition(int value, int position)
{
var result = value / (int)Math.Pow(10, position);
result = result % 10;
return result;
}
And also this one to know the full value (i.e.: 111, position 3 = 100 , sorry I don't know the proper name):
public int FullValueAtPosition(int value, int position)
{
return this.ValueAtPosition(value, position) * (int)Math.Pow(10, position);
}
How about this:
protected static int FindNDigit(decimal value, int position)
{
var index = value.ToString().IndexOf(".");
position = position + index;
return (int)Char.GetNumericValue(value.ToString(), position);
}
None of the previous solutions worked for me, so here is a working one :
var result = value / Math.Pow(10, Math.Truncate((Math.Log10(value) + 1) - position));
return (int)(result % 10);

Categories

Resources