shunting yard algorithm with trigonometric functions - c#

I am working on implementing shunting yard algorithm in C#. Although it parses mathematical expressions with symbols( + , * - / and ^) pretty well.But for some reason it is not working for sine cosine functions . Like for example if I try to calculate sin(45) I get 0.707106 .
But when I try to parse expression like
sin(25)+cos(15+sin(25))+3 it gives me 0.43756 (Correct answer is: 2.19106879911)
sin(45)+cos(45) it gives me 0.715779 (Correct answer is: 1.414)
I have followed all the steps that are mentioned in this article at Wikipedia . I have trying this for a few days now but I am unable to make it work perfectly. Here is the main parsing function
private void parse()
{
//scan the input string
for (int j = 0; j < input.Length; j++)
{
if (Char.IsDigit(input[j])) //if its a number
{
string number = extractNumber(input, j); //extracts multiple digit number
j = currentposition; //increment the counter according to length of the digit
postfix += number + " ";
Console.WriteLine(postfix);
}
//if its a function character
else if(Char.IsLetter(input[j]) )
{
//its a letter
string function = getFunction(j); //get the function name
operators.Push( function );
j = currentposition;
}
else if(input[j] == ',') //if its a comma
{
while(operators.Peek() != "(")
{
postfix += input[j] + " ";
}
}
else if (IsAnOperator(input[j])) // if we have got an operator
{
if (operators.Count != 0 && IsHigherPrecedence(operators.Peek().ToCharArray()[0], input[j]))
{
while ( ( operators.Count != 0 && IsHigherPrecedence(operators.Peek().ToCharArray()[0], input[j]) ) )
{
postfix += operators.Pop() + " ";
}
}
operators.Push(Char.ToString(input[j]));
}
else if (input[j] == '(')
operators.Push(Char.ToString(input[j]));
else if (input[j] == ')')
{
while (operators.Count != 0 && operators.Peek() != "(")
postfix += operators.Pop() + " ";
operators.Pop();
}
} // end for loop
while(operators.Count > 0 )
postfix +=operators.Pop() + " ";
//Conversion Logic (postfix to final answer )
postfixtokens.AddRange( postfix.Split(' ') ) ;
for (int j = 0; j < postfixtokens.Count-1; j++)
{
if (IsAnOperator(postfixtokens[j][0]) && basket.Count > 1)
{
Double second = Double.Parse( basket.Pop() );
Double first = Double.Parse(basket.Pop() );
char op = postfixtokens[j][0];
Double result = ApplyOperation(op,second, first);
// Console.WriteLine("{0} {1} {2} = {3}", first, op, second, result);
basket.Push( result.ToString());
}
else if (IsAnOperator(postfixtokens[j][0]) && basket.Count == 1)
{
Double second = Double.Parse(basket.Pop());
Double first = 0.0;
char op = postfixtokens[j][0];
Double result = ApplyOperation(op, second, first);
// Console.WriteLine("{0} {1} {2} = {3}", first, op, second, result);
basket.Push(result.ToString() );
}
else if (Char.IsDigit(postfixtokens[j][0]))
{
basket.Push( postfixtokens[j] );
}
else if( isAFunction(postfixtokens[j]) )
{
//if its a single argument function
if (AllowedFunctions[postfixtokens[j]] == 1)
{
//single arg logic
if (postfixtokens[j] == "sin")
{
Double result = Math.Sin( Double.Parse(basket.Pop() )*Math.PI/180.0 );
//result = Math.PI / 180;
basket.Push(result.ToString());
}
else if (postfixtokens[j] == "cos")
{
Double result = Math.Cos( Double.Parse(basket.Pop() )*Math.PI/180.0 );
//result = Math.PI / 180;
basket.Push(result.ToString());
}
}
}
}
}
Moreover,
Here is the output of the program:
Input: 3+4*2/(1-5)^5^10
PostFix: 3 4 2 * 1 5 - 5 10 ^ ^ / +
Answer: 3
Input: 2+4
PostFix: 2 4 +
Answer: 6
Input Expression: -5-4
Input: -5-4
PostFix: 5 - 4 -
Answer: -9
Input: -4+3
PostFix: 4 - 3 +
Answer: -1
Input Expression: 4^(4^4)
Input: 4^(4^4)
PostFix: 4 4 4 ^ ^
Answer: 1.34078079299426E+154
Input: sin45
PostFix: 45 sin
Answer: 0.707106781186547 (correct)
//the faulty ones
Input: sin(25)+cos(15+sin(25))+3
PostFix: 25 15 25 sin + 3 + cos + sin
Answer: 0.437567038002202
Input: sin(45)+cos(45)
PostFix: 45 45 cos + sin
Answer: 0.71577935734684
New Cases:
Input: sin45+cos45
PostFix: 45 45 cos + sin
Answer: 0.71577935734684
Input: 2+sin30
PostFix: 2 30 sin +
Answer:2.5
Input: sin30+2
PostFix: 30 2 + sin
Answer: 0.529919264233205
Thats all.Can anybody point me what I am doing wrong.
Edit:
Here is the IsHigherPrecedance function and precedance enum
:
public enum Precedance { Plus =1,Minus=1,Multiply=2,Divide=2,Exponent=3,Unary = 4,Parenthesis=5 };
private bool IsHigherPrecedence(char a, char b)
{
Precedance f = getPrecedance(a);
Precedance s = getPrecedance(b);
if (f >= s)
return false;
else
return true;
}
public Precedance getPrecedance(char a)
{
if (a == '+')
return Precedance.Plus;
else if (a == '-')
return Precedance.Minus;
else if (a == '*')
return Precedance.Multiply;
else if (a == '/')
return Precedance.Divide;
else if (a == '^')
return Precedance.Exponent;
else if (Char.IsLetter(a))
return Precedance.Unary;
else if (a == '(' || a == ')')
return Precedance.Parenthesis;
else
return Precedance.Plus;
}
Now that these trigonometric function are single argument function, are they going to be parsed with some other logic or does this shunting yard algo works with such functions as well as well?
Regards.

There are a copule of problems here, but the primary one is that you are treating functions as operators, though they are not (intrinsic to this is that you call your stack "operators" as though that is the only thing that can be on it, not true). In particular, this branch:
else if (IsAnOperator(input[j])) // if we have got an operator
{
if (operators.Count != 0 && IsHigherPrecedence(operators.Peek().ToCharArray()[0], input[j]))
{
while ( ( operators.Count != 0 && IsHigherPrecedence(operators.Peek().ToCharArray()[0], input[j]) ) )
{
postfix += operators.Pop() + " ";
}
}
operators.Push(Char.ToString(input[j]));
}
needs to check to see if what's on the "operators" stack is actually an operator:
else if (IsAnOperator(input[j])) // if we have got an operator
{
while (operators.Count != 0
&& IsAnOperator(operators.Peek().ToCharArray()[0])
&& IsHigherPrecedence(operators.Peek().ToCharArray()[0], input[j]))
{
postfix += operators.Pop() + " ";
}
operators.Push(Char.ToString(input[j]));
}
Other issues include the branch that handles commas:
else if (input[j] == ',') //if its a comma
{
while (operators.Peek() != "(")
{
// this isnt right, but its not the problem
postfix += input[j] + " ";
// should be this:
postfix += operators.Pop() + " ";
}
}

If you use this library: https://github.com/leblancmeneses/NPEG
you could use this grammar to parse your expression.
Digit: (?<Digit>[0-9]+('.'[0-9]+)?);
(?<Trig>): 'sin(' Expr ')' / 'cos(' Expr ')';
Value: Digit / Trig / '(' Expr ')';
(?<Product>): Value ((?<Symbol>'*' / '/') Value)*;
(?<Sum>): Product ((?<Symbol>'+' / '-') Product)*;
(?<Expr>): Sum ;
Test it out here:
http://www.robusthaven.com/blog/parsing-expression-grammar/npeg-language-workbench
cos(25)+cos(15+sin(25.333))+3
((((12/3)+5-2*(81/9))+1))
nuget:
Install-Package NPEG
to see a sample evaluation of the AST for boolean algebra.

Related

Generate (pseudo-) base-26 number representation (similar to Excel column names) [duplicate]

How do you convert a numerical number to an Excel column name in C# without using automation getting the value directly from Excel.
Excel 2007 has a possible range of 1 to 16384, which is the number of columns that it supports. The resulting values should be in the form of excel column names, e.g. A, AA, AAA etc.
Here's how I do it:
private string GetExcelColumnName(int columnNumber)
{
string columnName = "";
while (columnNumber > 0)
{
int modulo = (columnNumber - 1) % 26;
columnName = Convert.ToChar('A' + modulo) + columnName;
columnNumber = (columnNumber - modulo) / 26;
}
return columnName;
}
If anyone needs to do this in Excel without VBA, here is a way:
=SUBSTITUTE(ADDRESS(1;colNum;4);"1";"")
where colNum is the column number
And in VBA:
Function GetColumnName(colNum As Integer) As String
Dim d As Integer
Dim m As Integer
Dim name As String
d = colNum
name = ""
Do While (d > 0)
m = (d - 1) Mod 26
name = Chr(65 + m) + name
d = Int((d - m) / 26)
Loop
GetColumnName = name
End Function
Sorry, this is Python instead of C#, but at least the results are correct:
def ColIdxToXlName(idx):
if idx < 1:
raise ValueError("Index is too small")
result = ""
while True:
if idx > 26:
idx, r = divmod(idx - 1, 26)
result = chr(r + ord('A')) + result
else:
return chr(idx + ord('A') - 1) + result
for i in xrange(1, 1024):
print "%4d : %s" % (i, ColIdxToXlName(i))
You might need conversion both ways, e.g from Excel column adress like AAZ to integer and from any integer to Excel. The two methods below will do just that. Assumes 1 based indexing, first element in your "arrays" are element number 1.
No limits on size here, so you can use adresses like ERROR and that would be column number 2613824 ...
public static string ColumnAdress(int col)
{
if (col <= 26) {
return Convert.ToChar(col + 64).ToString();
}
int div = col / 26;
int mod = col % 26;
if (mod == 0) {mod = 26;div--;}
return ColumnAdress(div) + ColumnAdress(mod);
}
public static int ColumnNumber(string colAdress)
{
int[] digits = new int[colAdress.Length];
for (int i = 0; i < colAdress.Length; ++i)
{
digits[i] = Convert.ToInt32(colAdress[i]) - 64;
}
int mul=1;int res=0;
for (int pos = digits.Length - 1; pos >= 0; --pos)
{
res += digits[pos] * mul;
mul *= 26;
}
return res;
}
I discovered an error in my first post, so I decided to sit down and do the the math. What I found is that the number system used to identify Excel columns is not a base 26 system, as another person posted. Consider the following in base 10. You can also do this with the letters of the alphabet.
Space:.........................S1, S2, S3 : S1, S2, S3
....................................0, 00, 000 :.. A, AA, AAA
....................................1, 01, 001 :.. B, AB, AAB
.................................... …, …, … :.. …, …, …
....................................9, 99, 999 :.. Z, ZZ, ZZZ
Total states in space: 10, 100, 1000 : 26, 676, 17576
Total States:...............1110................18278
Excel numbers columns in the individual alphabetical spaces using base 26. You can see that in general, the state space progression is a, a^2, a^3, … for some base a, and the total number of states is a + a^2 + a^3 + … .
Suppose you want to find the total number of states A in the first N spaces. The formula for doing so is A = (a)(a^N - 1 )/(a-1). This is important because we need to find the space N that corresponds to our index K. If I want to find out where K lies in the number system I need to replace A with K and solve for N. The solution is N = log{base a} (A (a-1)/a +1). If I use the example of a = 10 and K = 192, I know that N = 2.23804… . This tells me that K lies at the beginning of the third space since it is a little greater than two.
The next step is to find exactly how far in the current space we are. To find this, subtract from K the A generated using the floor of N. In this example, the floor of N is two. So, A = (10)(10^2 – 1)/(10-1) = 110, as is expected when you combine the states of the first two spaces. This needs to be subtracted from K because these first 110 states would have already been accounted for in the first two spaces. This leaves us with 82 states. So, in this number system, the representation of 192 in base 10 is 082.
The C# code using a base index of zero is
private string ExcelColumnIndexToName(int Index)
{
string range = string.Empty;
if (Index < 0 ) return range;
int a = 26;
int x = (int)Math.Floor(Math.Log((Index) * (a - 1) / a + 1, a));
Index -= (int)(Math.Pow(a, x) - 1) * a / (a - 1);
for (int i = x+1; Index + i > 0; i--)
{
range = ((char)(65 + Index % a)).ToString() + range;
Index /= a;
}
return range;
}
//Old Post
A zero-based solution in C#.
private string ExcelColumnIndexToName(int Index)
{
string range = "";
if (Index < 0 ) return range;
for(int i=1;Index + i > 0;i=0)
{
range = ((char)(65 + Index % 26)).ToString() + range;
Index /= 26;
}
if (range.Length > 1) range = ((char)((int)range[0] - 1)).ToString() + range.Substring(1);
return range;
}
This answer is in javaScript:
function getCharFromNumber(columnNumber){
var dividend = columnNumber;
var columnName = "";
var modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = String.fromCharCode(65 + modulo).toString() + columnName;
dividend = parseInt((dividend - modulo) / 26);
}
return columnName;
}
Easy with recursion.
public static string GetStandardExcelColumnName(int columnNumberOneBased)
{
int baseValue = Convert.ToInt32('A');
int columnNumberZeroBased = columnNumberOneBased - 1;
string ret = "";
if (columnNumberOneBased > 26)
{
ret = GetStandardExcelColumnName(columnNumberZeroBased / 26) ;
}
return ret + Convert.ToChar(baseValue + (columnNumberZeroBased % 26) );
}
I'm surprised all of the solutions so far contain either iteration or recursion.
Here's my solution that runs in constant time (no loops). This solution works for all possible Excel columns and checks that the input can be turned into an Excel column. Possible columns are in the range [A, XFD] or [1, 16384]. (This is dependent on your version of Excel)
private static string Turn(uint col)
{
if (col < 1 || col > 16384) //Excel columns are one-based (one = 'A')
throw new ArgumentException("col must be >= 1 and <= 16384");
if (col <= 26) //one character
return ((char)(col + 'A' - 1)).ToString();
else if (col <= 702) //two characters
{
char firstChar = (char)((int)((col - 1) / 26) + 'A' - 1);
char secondChar = (char)(col % 26 + 'A' - 1);
if (secondChar == '#') //Excel is one-based, but modulo operations are zero-based
secondChar = 'Z'; //convert one-based to zero-based
return string.Format("{0}{1}", firstChar, secondChar);
}
else //three characters
{
char firstChar = (char)((int)((col - 1) / 702) + 'A' - 1);
char secondChar = (char)((col - 1) / 26 % 26 + 'A' - 1);
char thirdChar = (char)(col % 26 + 'A' - 1);
if (thirdChar == '#') //Excel is one-based, but modulo operations are zero-based
thirdChar = 'Z'; //convert one-based to zero-based
return string.Format("{0}{1}{2}", firstChar, secondChar, thirdChar);
}
}
Same implementation in Java
public String getExcelColumnName (int columnNumber)
{
int dividend = columnNumber;
int i;
String columnName = "";
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
i = 65 + modulo;
columnName = new Character((char)i).toString() + columnName;
dividend = (int)((dividend - modulo) / 26);
}
return columnName;
}
int nCol = 127;
string sChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol >= 26)
{
int nChar = nCol % 26;
nCol = (nCol - nChar) / 26;
// You could do some trick with using nChar as offset from 'A', but I am lazy to do it right now.
sCol = sChars[nChar] + sCol;
}
sCol = sChars[nCol] + sCol;
Update: Peter's comment is right. That's what I get for writing code in the browser. :-) My solution was not compiling, it was missing the left-most letter and it was building the string in reverse order - all now fixed.
Bugs aside, the algorithm is basically converting a number from base 10 to base 26.
Update 2: Joel Coehoorn is right - the code above will return AB for 27. If it was real base 26 number, AA would be equal to A and the next number after Z would be BA.
int nCol = 127;
string sChars = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol > 26)
{
int nChar = nCol % 26;
if (nChar == 0)
nChar = 26;
nCol = (nCol - nChar) / 26;
sCol = sChars[nChar] + sCol;
}
if (nCol != 0)
sCol = sChars[nCol] + sCol;
..And converted to php:
function GetExcelColumnName($columnNumber) {
$columnName = '';
while ($columnNumber > 0) {
$modulo = ($columnNumber - 1) % 26;
$columnName = chr(65 + $modulo) . $columnName;
$columnNumber = (int)(($columnNumber - $modulo) / 26);
}
return $columnName;
}
Just throwing in a simple two-line C# implementation using recursion, because all the answers here seem far more complicated than necessary.
/// <summary>
/// Gets the column letter(s) corresponding to the given column number.
/// </summary>
/// <param name="column">The one-based column index. Must be greater than zero.</param>
/// <returns>The desired column letter, or an empty string if the column number was invalid.</returns>
public static string GetColumnLetter(int column) {
if (column < 1) return String.Empty;
return GetColumnLetter((column - 1) / 26) + (char)('A' + (column - 1) % 26);
}
Although there are already a bunch of valid answers1, none get into the theory behind it.
Excel column names are bijective base-26 representations of their number. This is quite different than an ordinary base 26 (there is no leading zero), and I really recommend reading the Wikipedia entry to grasp the differences. For example, the decimal value 702 (decomposed in 26*26 + 26) is represented in "ordinary" base 26 by 110 (i.e. 1x26^2 + 1x26^1 + 0x26^0) and in bijective base-26 by ZZ (i.e. 26x26^1 + 26x26^0).
Differences aside, bijective numeration is a positional notation, and as such we can perform conversions using an iterative (or recursive) algorithm which on each iteration finds the digit of the next position (similarly to an ordinary base conversion algorithm).
The general formula to get the digit at the last position (the one indexed 0) of the bijective base-k representation of a decimal number m is (f being the ceiling function minus 1):
m - (f(m / k) * k)
The digit at the next position (i.e. the one indexed 1) is found by applying the same formula to the result of f(m / k). We know that for the last digit (i.e. the one with the highest index) f(m / k) is 0.
This forms the basis for an iteration that finds each successive digit in bijective base-k of a decimal number. In pseudo-code it would look like this (digit() maps a decimal integer to its representation in the bijective base -- e.g. digit(1) would return A in bijective base-26):
fun conv(m)
q = f(m / k)
a = m - (q * k)
if (q == 0)
return digit(a)
else
return conv(q) + digit(a);
So we can translate this to C#2 to get a generic3 "conversion to bijective base-k" ToBijective() routine:
class BijectiveNumeration {
private int baseK;
private Func<int, char> getDigit;
public BijectiveNumeration(int baseK, Func<int, char> getDigit) {
this.baseK = baseK;
this.getDigit = getDigit;
}
public string ToBijective(double decimalValue) {
double q = f(decimalValue / baseK);
double a = decimalValue - (q * baseK);
return ((q > 0) ? ToBijective(q) : "") + getDigit((int)a);
}
private static double f(double i) {
return (Math.Ceiling(i) - 1);
}
}
Now for conversion to bijective base-26 (our "Excel column name" use case):
static void Main(string[] args)
{
BijectiveNumeration bijBase26 = new BijectiveNumeration(
26,
(value) => Convert.ToChar('A' + (value - 1))
);
Console.WriteLine(bijBase26.ToBijective(1)); // prints "A"
Console.WriteLine(bijBase26.ToBijective(26)); // prints "Z"
Console.WriteLine(bijBase26.ToBijective(27)); // prints "AA"
Console.WriteLine(bijBase26.ToBijective(702)); // prints "ZZ"
Console.WriteLine(bijBase26.ToBijective(16384)); // prints "XFD"
}
Excel's maximum column index is 16384 / XFD, but this code will convert any positive number.
As an added bonus, we can now easily convert to any bijective base. For example for bijective base-10:
static void Main(string[] args)
{
BijectiveNumeration bijBase10 = new BijectiveNumeration(
10,
(value) => value < 10 ? Convert.ToChar('0'+value) : 'A'
);
Console.WriteLine(bijBase10.ToBijective(1)); // prints "1"
Console.WriteLine(bijBase10.ToBijective(10)); // prints "A"
Console.WriteLine(bijBase10.ToBijective(123)); // prints "123"
Console.WriteLine(bijBase10.ToBijective(20)); // prints "1A"
Console.WriteLine(bijBase10.ToBijective(100)); // prints "9A"
Console.WriteLine(bijBase10.ToBijective(101)); // prints "A1"
Console.WriteLine(bijBase10.ToBijective(2010)); // prints "19AA"
}
1 This generic answer can eventually be reduced to the other, correct, specific answers, but I find it hard to fully grasp the logic of the solutions without the formal theory behind bijective numeration in general. It also proves its correctness nicely. Additionally, several similar questions link back to this one, some being language-agnostic or more generic. That's why I thought the addition of this answer was warranted, and that this question was a good place to put it.
2 C# disclaimer: I implemented an example in C# because this is what is asked here, but I have never learned nor used the language. I have verified it does compile and run, but please adapt it to fit the language best practices / general conventions, if necessary.
3 This example only aims to be correct and understandable ; it could and should be optimized would performance matter (e.g. with tail-recursion -- but that seems to require trampolining in C#), and made safer (e.g. by validating parameters).
I wanted to throw in my static class I use, for interoping between col index and col Label. I use a modified accepted answer for my ColumnLabel Method
public static class Extensions
{
public static string ColumnLabel(this int col)
{
var dividend = col;
var columnLabel = string.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnLabel = Convert.ToChar(65 + modulo).ToString() + columnLabel;
dividend = (int)((dividend - modulo) / 26);
}
return columnLabel;
}
public static int ColumnIndex(this string colLabel)
{
// "AD" (1 * 26^1) + (4 * 26^0) ...
var colIndex = 0;
for(int ind = 0, pow = colLabel.Count()-1; ind < colLabel.Count(); ++ind, --pow)
{
var cVal = Convert.ToInt32(colLabel[ind]) - 64; //col A is index 1
colIndex += cVal * ((int)Math.Pow(26, pow));
}
return colIndex;
}
}
Use this like...
30.ColumnLabel(); // "AD"
"AD".ColumnIndex(); // 30
private String getColumn(int c) {
String s = "";
do {
s = (char)('A' + (c % 26)) + s;
c /= 26;
} while (c-- > 0);
return s;
}
Its not exactly base 26, there is no 0 in the system. If there was, 'Z' would be followed by 'BA' not by 'AA'.
if you just want it for a cell formula without code, here's a formula for it:
IF(COLUMN()>=26,CHAR(ROUND(COLUMN()/26,1)+64)&CHAR(MOD(COLUMN(),26)+64),CHAR(COLUMN()+64))
In Delphi (Pascal):
function GetExcelColumnName(columnNumber: integer): string;
var
dividend, modulo: integer;
begin
Result := '';
dividend := columnNumber;
while dividend > 0 do begin
modulo := (dividend - 1) mod 26;
Result := Chr(65 + modulo) + Result;
dividend := (dividend - modulo) div 26;
end;
end;
A little late to the game, but here's the code I use (in C#):
private static readonly string _Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static int ColumnNameParse(string value)
{
// assumes value.Length is [1,3]
// assumes value is uppercase
var digits = value.PadLeft(3).Select(x => _Alphabet.IndexOf(x));
return digits.Aggregate(0, (current, index) => (current * 26) + (index + 1));
}
In perl, for an input of 1 (A), 27 (AA), etc.
sub excel_colname {
my ($idx) = #_; # one-based column number
--$idx; # zero-based column index
my $name = "";
while ($idx >= 0) {
$name .= chr(ord("A") + ($idx % 26));
$idx = int($idx / 26) - 1;
}
return scalar reverse $name;
}
Though I am late to the game, Graham's answer is far from being optimal. Particularly, you don't have to use the modulo, call ToString() and apply (int) cast. Considering that in most cases in C# world you would start numbering from 0, here is my revision:
public static string GetColumnName(int index) // zero-based
{
const byte BASE = 'Z' - 'A' + 1;
string name = String.Empty;
do
{
name = Convert.ToChar('A' + index % BASE) + name;
index = index / BASE - 1;
}
while (index >= 0);
return name;
}
More than 30 solutions already, but here's my one-line C# solution...
public string IntToExcelColumn(int i)
{
return ((i<16926? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + (i<2730? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + (i<26? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + ((char)((i%26)+65)));
}
After looking at all the supplied Versions here, I decided to do one myself, using recursion.
Here is my vb.net Version:
Function CL(ByVal x As Integer) As String
If x >= 1 And x <= 26 Then
CL = Chr(x + 64)
Else
CL = CL((x - x Mod 26) / 26) & Chr((x Mod 26) + 1 + 64)
End If
End Function
Refining the original solution (in C#):
public static class ExcelHelper
{
private static Dictionary<UInt16, String> l_DictionaryOfColumns;
public static ExcelHelper() {
l_DictionaryOfColumns = new Dictionary<ushort, string>(256);
}
public static String GetExcelColumnName(UInt16 l_Column)
{
UInt16 l_ColumnCopy = l_Column;
String l_Chars = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String l_rVal = "";
UInt16 l_Char;
if (l_DictionaryOfColumns.ContainsKey(l_Column) == true)
{
l_rVal = l_DictionaryOfColumns[l_Column];
}
else
{
while (l_ColumnCopy > 26)
{
l_Char = l_ColumnCopy % 26;
if (l_Char == 0)
l_Char = 26;
l_ColumnCopy = (l_ColumnCopy - l_Char) / 26;
l_rVal = l_Chars[l_Char] + l_rVal;
}
if (l_ColumnCopy != 0)
l_rVal = l_Chars[l_ColumnCopy] + l_rVal;
l_DictionaryOfColumns.ContainsKey(l_Column) = l_rVal;
}
return l_rVal;
}
}
Here is an Actionscript version:
private var columnNumbers:Array = ['A', 'B', 'C', 'D', 'E', 'F' , 'G', 'H', 'I', 'J', 'K' ,'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
private function getExcelColumnName(columnNumber:int) : String{
var dividend:int = columnNumber;
var columnName:String = "";
var modulo:int;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = columnNumbers[modulo] + columnName;
dividend = int((dividend - modulo) / 26);
}
return columnName;
}
JavaScript Solution
/**
* Calculate the column letter abbreviation from a 1 based index
* #param {Number} value
* #returns {string}
*/
getColumnFromIndex = function (value) {
var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
var remainder, result = "";
do {
remainder = value % 26;
result = base[(remainder || 26) - 1] + result;
value = Math.floor(value / 26);
} while (value > 0);
return result;
};
These my codes to convert specific number (index start from 1) to Excel Column.
public static string NumberToExcelColumn(uint number)
{
uint originalNumber = number;
uint numChars = 1;
while (Math.Pow(26, numChars) < number)
{
numChars++;
if (Math.Pow(26, numChars) + 26 >= number)
{
break;
}
}
string toRet = "";
uint lastValue = 0;
do
{
number -= lastValue;
double powerVal = Math.Pow(26, numChars - 1);
byte thisCharIdx = (byte)Math.Truncate((columnNumber - 1) / powerVal);
lastValue = (int)powerVal * thisCharIdx;
if (numChars - 2 >= 0)
{
double powerVal_next = Math.Pow(26, numChars - 2);
byte thisCharIdx_next = (byte)Math.Truncate((columnNumber - lastValue - 1) / powerVal_next);
int lastValue_next = (int)Math.Pow(26, numChars - 2) * thisCharIdx_next;
if (thisCharIdx_next == 0 && lastValue_next == 0 && powerVal_next == 26)
{
thisCharIdx--;
lastValue = (int)powerVal * thisCharIdx;
}
}
toRet += (char)((byte)'A' + thisCharIdx + ((numChars > 1) ? -1 : 0));
numChars--;
} while (numChars > 0);
return toRet;
}
My Unit Test:
[TestMethod]
public void Test()
{
Assert.AreEqual("A", NumberToExcelColumn(1));
Assert.AreEqual("Z", NumberToExcelColumn(26));
Assert.AreEqual("AA", NumberToExcelColumn(27));
Assert.AreEqual("AO", NumberToExcelColumn(41));
Assert.AreEqual("AZ", NumberToExcelColumn(52));
Assert.AreEqual("BA", NumberToExcelColumn(53));
Assert.AreEqual("ZZ", NumberToExcelColumn(702));
Assert.AreEqual("AAA", NumberToExcelColumn(703));
Assert.AreEqual("ABC", NumberToExcelColumn(731));
Assert.AreEqual("ACQ", NumberToExcelColumn(771));
Assert.AreEqual("AYZ", NumberToExcelColumn(1352));
Assert.AreEqual("AZA", NumberToExcelColumn(1353));
Assert.AreEqual("AZB", NumberToExcelColumn(1354));
Assert.AreEqual("BAA", NumberToExcelColumn(1379));
Assert.AreEqual("CNU", NumberToExcelColumn(2413));
Assert.AreEqual("GCM", NumberToExcelColumn(4823));
Assert.AreEqual("MSR", NumberToExcelColumn(9300));
Assert.AreEqual("OMB", NumberToExcelColumn(10480));
Assert.AreEqual("ULV", NumberToExcelColumn(14530));
Assert.AreEqual("XFD", NumberToExcelColumn(16384));
}
Sorry, this is Python instead of C#, but at least the results are correct:
def excel_column_number_to_name(column_number):
output = ""
index = column_number-1
while index >= 0:
character = chr((index%26)+ord('A'))
output = output + character
index = index/26 - 1
return output[::-1]
for i in xrange(1, 1024):
print "%4d : %s" % (i, excel_column_number_to_name(i))
Passed these test cases:
Column Number: 494286 => ABCDZ
Column Number: 27 => AA
Column Number: 52 => AZ
For what it is worth, here is Graham's code in Powershell:
function ConvertTo-ExcelColumnID {
param (
[parameter(Position = 0,
HelpMessage = "A 1-based index to convert to an excel column ID. e.g. 2 => 'B', 29 => 'AC'",
Mandatory = $true)]
[int]$index
);
[string]$result = '';
if ($index -le 0 ) {
return $result;
}
while ($index -gt 0) {
[int]$modulo = ($index - 1) % 26;
$character = [char]($modulo + [int][char]'A');
$result = $character + $result;
[int]$index = ($index - $modulo) / 26;
}
return $result;
}
Another VBA way
Public Function GetColumnName(TargetCell As Range) As String
GetColumnName = Split(CStr(TargetCell.Cells(1, 1).Address), "$")(1)
End Function
Here's my super late implementation in PHP. This one's recursive. I wrote it just before I found this post. I wanted to see if others had solved this problem already...
public function GetColumn($intNumber, $strCol = null) {
if ($intNumber > 0) {
$intRem = ($intNumber - 1) % 26;
$strCol = $this->GetColumn(intval(($intNumber - $intRem) / 26), sprintf('%s%s', chr(65 + $intRem), $strCol));
}
return $strCol;
}

Naughts and Crosses (Tic Tac Toe), subroutine query

So I'm at the final stage of my Noughts and Crosses project and I'm quite dearly stuck, I have done move validation subroutine as well as a subroutine that is solely based on changing the blank space in the box into an " X " or an " O ",
yet my code seems to tell me that some part of my code does not exist in the current context and I am completely baffled
The code is:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[,] grid = new string[3, 3] {{" "," "," "},
{" "," "," "},
{" "," "," "}};
string board = System.IO.File.ReadAllText("E:\\BoardGame.txt");
Console.WriteLine(board);
int player = 0;
var XCoordinate = 0;
var YCoordinate = 0;
int x, y;
GetMoveCoordinates(ref XCoordinate, ref YCoordinate);
if (player == 0)
{
grid[XCoordinate, YCoordinate] = " X ";
player++;
}
else
{
grid[XCoordinate, YCoordinate] = " O ";
player--;
}
UpdateGrid(grid, box);
if (player == 1)
{
}
}
public static void GetMoveCoordinates(ref int XCoordinate, ref int YCoordinate)
{
int CommaLocation;
bool GameHasBeenWon = false;
string CoordinatesInput;
string XChar, YChar;
while (GameHasBeenWon == false)
{
try
{
Console.Write("Enter your coordinates: (x,y) ");
CoordinatesInput = Console.ReadLine();
CommaLocation = CoordinatesInput.IndexOf(",".ToString());
XChar = CoordinatesInput.Substring(CommaLocation - 1, CommaLocation);
YChar = CoordinatesInput.Substring(CommaLocation + 1);
XCoordinate = int.Parse(XChar);
YCoordinate = int.Parse(YChar);
}
catch
{
Console.WriteLine("Invalid Input- Please Try Again");
}
}
}
public static bool CheckValidMove(int XCoordinate, int YCoordinate, string[,] Board)
{
if ((XCoordinate >= 1) || (XCoordinate <= 3))
{
if ((YCoordinate >= 1) || (YCoordinate <= 3))
{
if ((Board[XCoordinate, YCoordinate]) == " ")
{
return true;
}
else return false;
}
else return false;
}
else return false;
}
public static void UpdateGrid(string[,] grid, string box)
{
Console.Clear();
for (int x = 0; x < grid.GetLength(0); x++)
{
for (int y = 0; y < grid.GetLength(1); y++)
{
box = box.Replace((x + 1) + "," + (y + 1), grid[y, x]);
}
}
// In the case not required as clearning the console default the cursor back to 0,0, but left in
// as an example
Console.SetCursorPosition(0, 0);
Console.WriteLine(box);
}
}
}
Yet the problem I seem to have is under Main, under the if statement where the code seems to tell me that box in the Update(grid,box), does not exist in the current context, yet it should do in the last subroutine? Am I supposed to do it as a ref statement or am I missing something? Also if you have any tips on how to tidy up the code I'd gladly appreciate it (yes I will add win parameters but I'd like to draw my symbols first).
This is what the grid looks like this:
+---+---+---+
| | | |
+---+---+---+
| | | |
+---+---+---+
| | | |
+---+---+---+
There are several bugs here. First, the following won't compile:
UpdateGrid(grid, box);
As Andrew Whitaker indicated in the comments, there is no "box" variable in your main method (you never declared or initialized it). Define what that variable is and initialize it properly and that'll compile again.
Next, a quick stylistic note on the following:
while (GameHasBeenWon == false)
Don't explicitly compare to true and false - the correct way to do this is
while (!GameHasBeenWon)
The next line to comment on has several bugs:
(XCoordinate >= 1) || (XCoordinate <= 3)
This means that XCoordinate >= 1 OR it's less than or equal to 3, which isn't at all what you meant. Actually, by this logic, any integer is valid because it's either greater than 1, equal to 1, less than 3, or equal to 3. (Think about it - for what integers could a statement like this possibly be false?) Also, 3 is specifically not a valid index, but 0 is. Keep in mind that arrays are zero-indexed. Thus, this should actually be
(XCoordinate >= 0) && (XCoordinate < 3)
In terms of your if statements:
if ((Board[XCoordinate, YCoordinate]) == " ")
{
return true;
}
else return false;
returns true exactly when (Board[XCoordinate, YCoordinate]) == " " is true and false exactly when that statement is false. You could just do
return (Board[XCoordinate, YCoordinate]) == " ";
In fact, you could do that for the whole "if" statement. (I'm not sitting in front of an IDE right now so I apologize if my syntax isn't perfect here).
return ((XCoordinate >= 0) && (XCoordinate < 3) &&
((YCoordinate >= 0) && (YCoordinate < 3)) &&
((Board[XCoordinate, YCoordinate]) == " "));

String format numbers to millions, thousands with rounding

I'm trying to format a price for display, and I want to display a number with the million (M) or thousands (K) suffix, but only ever display at most 3 values, rounded down.
I found this question which is very close to what I want, but doesn't handle rounding (specifically, always rounding down)
Likewise, with this question you have no control over the rounding.
Sample input/expected output:
1 = 1
10 = 10
100 = 100
1000 = 1K
100000 = 100K
125000 = 125K
125900 = 125K
1000000 = 1M
1250000 = 1.25M
1258000 = 1.25M
10000000 = 10M
10500000 = 10.5M
100000000 = 100M
100100000 = 100M
I essentially only ever want to display 3 values.
I can't see how i can use the "," custom specifier and specify rounding.
My initial thinking suggests I need to use a combination of the above, Math.Floor and some .ToString() formatting magic, but i'm not really sure where to start.
Can someone help me out?
Thanks in advance.
This should help, combined with one of the formatting techniques in the other questions you've linked to.
internal long MaxThreeSignificantDigits(long x)
{
int i = (int)Math.Log10(x);
i = Math.Max(0, i - 2);
i = (int)Math.Pow(10, i);
return x / i * i;
}
EDIT:
OK, how about this?
Console.WriteLine(SO30180672.FormatNumber(1));
Console.WriteLine(SO30180672.FormatNumber(12));
Console.WriteLine(SO30180672.FormatNumber(123));
Console.WriteLine(SO30180672.FormatNumber(1234));
Console.WriteLine(SO30180672.FormatNumber(12345));
Console.WriteLine(SO30180672.FormatNumber(123456));
Console.WriteLine(SO30180672.FormatNumber(1234567));
Console.WriteLine(SO30180672.FormatNumber(12345678));
Console.WriteLine(SO30180672.FormatNumber(123456789));
Following is partially copied from here: https://stackoverflow.com/a/23384710/253938
internal class SO30180672
{
internal static string FormatNumber(long num)
{
num = MaxThreeSignificantDigits(num);
if (num >= 100000000)
return (num / 1000000D).ToString("0.#M");
if (num >= 1000000)
return (num / 1000000D).ToString("0.##M");
if (num >= 100000)
return (num / 1000D).ToString("0k");
if (num >= 100000)
return (num / 1000D).ToString("0.#k");
if (num >= 1000)
return (num / 1000D).ToString("0.##k");
return num.ToString("#,0");
}
internal static long MaxThreeSignificantDigits(long x)
{
int i = (int)Math.Log10(x);
i = Math.Max(0, i - 2);
i = (int)Math.Pow(10, i);
return x / i * i;
}
}
EDIT 2 - thank you very much to #Rhexis
internal class SO30180672
{
internal static void RunTest()
{
Console.WriteLine(FormatNumber(1));
Console.WriteLine(FormatNumber(10));
Console.WriteLine(FormatNumber(100));
Console.WriteLine(FormatNumber(1000));
Console.WriteLine(FormatNumber(10000));
Console.WriteLine(FormatNumber(100000));
Console.WriteLine(FormatNumber(125000));
Console.WriteLine(FormatNumber(125900));
Console.WriteLine(FormatNumber(1000000));
Console.WriteLine(FormatNumber(1250000));
Console.WriteLine(FormatNumber(1258000));
Console.WriteLine(FormatNumber(10000000));
Console.WriteLine(FormatNumber(10500000));
Console.WriteLine(FormatNumber(100000000));
Console.WriteLine(FormatNumber(100100000));
}
private static string FormatNumber(long num)
{
// Ensure number has max 3 significant digits (no rounding up can happen)
long i = (long)Math.Pow(10, (int)Math.Max(0, Math.Log10(num) - 2));
num = num / i * i;
if (num >= 1000000000)
return (num / 1000000000D).ToString("0.##") + "B";
if (num >= 1000000)
return (num / 1000000D).ToString("0.##") + "M";
if (num >= 1000)
return (num / 1000D).ToString("0.##") + "K";
return num.ToString("#,0");
}
}
This is my code with test outputs
1249 1.24K
12499 12.4K
124999 124K
1249999 1.24M
12499999 12.4M
124999999 124M
1249999999 1.24B
The code will output three digits at maximum.
static string FormatNumber(uint n)
{
if (n < 1000)
return n.ToString();
if (n < 10000)
return String.Format("{0:#,.##}K", n - 5);
if (n < 100000)
return String.Format("{0:#,.#}K", n - 50);
if (n < 1000000)
return String.Format("{0:#,.}K", n - 500);
if (n < 10000000)
return String.Format("{0:#,,.##}M", n - 5000);
if (n < 100000000)
return String.Format("{0:#,,.#}M", n - 50000);
if (n < 1000000000)
return String.Format("{0:#,,.}M", n - 500000);
return String.Format("{0:#,,,.##}B", n - 5000000);
}
Since the format essentially changes based on the range you'll most likely need some conditional formatting similar to below. I have only tested the sample set provided, so make sure this works for the full range of expected values.
class Program
{
static void Main(String[] args)
{
Console.WriteLine(RoundAndFormat(1));
Console.WriteLine(RoundAndFormat(10));
Console.WriteLine(RoundAndFormat(100));
Console.WriteLine(RoundAndFormat(1000));
Console.WriteLine(RoundAndFormat(100000));
Console.WriteLine(RoundAndFormat(125000));
Console.WriteLine(RoundAndFormat(125900));
Console.WriteLine(RoundAndFormat(1000000));
Console.WriteLine(RoundAndFormat(1250000));
Console.WriteLine(RoundAndFormat(1258000));
Console.WriteLine(RoundAndFormat(10000000));
Console.WriteLine(RoundAndFormat(10500000));
Console.WriteLine(RoundAndFormat(100000000));
Console.WriteLine(RoundAndFormat(100100000));
Console.ReadLine();
}
public static String RoundAndFormat(Int32 value)
{
var result = String.Empty;
var negative = value < 0;
if (negative) value = value * -1;
if (value < 1000)
{
result = value.ToString();
}
else if (value < 1000000)
{
result = RoundDown(value / 1000.0, 0) + "K";
}
else if (value < 100000000)
{
result = RoundDown(value / 1000000.0, 2) + "M";
}
else if (value < 10000000000)
{
result = RoundDown(value / 1000000.0, 0) + "M";
}
if (negative) return "-" + result;
return result;
}
public static Double RoundDown(Double value, Int32 digits)
{
var pow = Math.Pow(10, digits);
return Math.Truncate(value * pow) / pow;
}
Thanks for your help everyone, it got me on the right track to figuring it out myself.
public static string FormatPriceValue(this int num)
{
if (num >= 100000000)
{
return ((num >= 10050000 ? num - 500000 : num) / 1000000D).ToString("#M");
}
if (num >= 10000000)
{
return ((num >= 10500000 ? num - 50000 : num) / 1000000D).ToString("0.#M");
}
if (num >= 1000000)
{
return ((num >= 1005000 ? num-5000 : num) / 1000000D).ToString("0.##M");
}
if (num >= 100000)
{
return ((num >= 100500 ? num - 500 : num) / 1000D).ToString("0.k");
}
if (num >= 10000)
{
return ((num >= 10550 ? num - 50 : num) / 1000D).ToString("0.#k");
}
return num >= 1000 ? ((num >= 1005 ? num - 5 : num) / 1000D).ToString("0.##k") : num.ToString("#,0");
}
I know this is an old question but I can't help but notice most of these answers are not far expandable, most of them are very similar lines of code repeated for more values. I needed something that worked on bigger values so instead of repetetive code I tried using math in a smart way. This does require using floating point math (doubles) as the maximum value of an unsigned long is only 1.84e+19. My solution:
public static string GetStringRepresentation(double count)
{
string tokens = " KMBtqQsSondUDT"; //Infinitely expandable (at least to the limit of double floating point values)
for (double i = 1; true; i += 1)
{
double val = Math.Pow(1000, i);
if (val > count)
{
return $"{count / Math.Pow(1000, i - 1)}{tokens[(int)i - 1]}".Trim();
}
}
}
Test code:
Console.WriteLine(" 1: " + GetStringRepresentation( 1).PadLeft(7, ' '));
Console.WriteLine(" 12: " + GetStringRepresentation( 12).PadLeft(7, ' '));
Console.WriteLine(" 123: " + GetStringRepresentation( 123).PadLeft(7, ' '));
Console.WriteLine(" 1230: " + GetStringRepresentation( 1230).PadLeft(7, ' '));
Console.WriteLine(" 12340: " + GetStringRepresentation( 12340).PadLeft(7, ' '));
Console.WriteLine(" 123450: " + GetStringRepresentation( 123450).PadLeft(7, ' '));
Console.WriteLine(" 1230000: " + GetStringRepresentation( 1230000).PadLeft(7, ' '));
Console.WriteLine(" 12340000: " + GetStringRepresentation( 12340000).PadLeft(7, ' '));
Console.WriteLine(" 123450000: " + GetStringRepresentation( 123450000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000: " + GetStringRepresentation( 1230000000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000000: " + GetStringRepresentation( 1230000000000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000000000: " + GetStringRepresentation( 1230000000000000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000000000000: " + GetStringRepresentation(1230000000000000000).PadLeft(7, ' '));
Output:
1: 1
12: 12
123: 123
1230: 1,23K
12340: 12,34K
123450: 123,45K
1230000: 1,23M
12340000: 12,34M
123450000: 123,45M
1230000000: 1,23B
1230000000000: 1,23t
1230000000000000: 1,23q
1230000000000000000: 1,23Q
Below is a VBS/VbScript Function to do that.
NB => VB and VBA offer direct format call.
' Usage: Return a number using it's greatert thousand symbol (ex: 234,789,145 = 234.8M)
Function Format_Large_Number(nb, nbDigit)
' Safety
If Not IsNumeric(nb) Then FormatLargeNumber = nb : Exit Function
If nbDigit < 1 Then nbDigit = 1
If nbDigit > 3 Then nbDigit = 3
' Initiate var
Dim rtnNb : rtnNb = nb
Dim nbFormat : nbFormat = FormatCurrency(rtnNb, 0, vbTrue, vbTrue)
nbFormat = Trim(Replace(nbFormat, "$", ""))
Dim nbSymbol : nbSymbol = ""
Dim nbDecRnd : nbDecRnd = ""
Dim arrNb : arrNb = Split(nbFormat, " ")
' Asign symbol
Select Case UBound(arrNb)
Case 0
nbSymbol = "" ' Hundred
Case 1
nbSymbol = "K" ' Thousand
Case 2
nbSymbol = "M" ' Million
Case 3
nbSymbol = "G" ' Billion
Case 4
nbSymbol = "T" ' Trillion
Case 5
nbSymbol = "P" ' Quadrillion
Case 6
nbSymbol = "E" ' Quintillion
End Select
' Concatenate rtn string
If Ubound(arrNb) > 0 Then
If nbDigit < 3 Then
If CInt(arrNb(1)) > 499 Then
nbDecRnd = CStr(CInt(Left(arrNb(1),nbDigit)) + 1) ' Ceil decimal rtn
Else
nbDecRnd = Left(arrNb(1),nbDigit)
End If
Else
nbDecRnd = Left(arrNb(1),nbDigit)
End If
rtnNb = arrNb(0) & "," & nbDecRnd & nbSymbol ' All others
Else
rtnNb = arrNb(0) & nbSymbol ' Hundred
End If
' Rtn value
Format_Large_Number = rtnNb
End Function

Splitting string and performing calculations from delimited string tokens C#

I delimited the string expression "1 plus 1 minus 2 plus 2 minus 2 minus 5 plus 10".Gathered the tokens in string[] and started coding Jargon.
1 plus 1 minus 2 plus 2 minus 2 minus 5 plus 10=5
public int Calculate(string expression)
{
//TODO: implement this
if (string.IsNullOrEmpty(expression))
return 0;
//expression = "100 plus 100 minus 200";
string[] tokens = expression.Split();
int i= 0;
int result=0;
for (; i < tokens.Length; )
{
int a = 0;
int b = 0;
if (i < 1)
{
a = int.Parse(tokens[i]);
i++;
}
else if (i % 2 != 0 && tokens[i].ToString() == "plus")
{
i++;
b = int.Parse(tokens[i]);
a = result;
result = a + b;
i = i + 2;
}
if (tokens[i].ToString() == "plus")
{
i++;
b = int.Parse(tokens[i]);
result += a + b;
i = i + 2;
}
else if(i>1)
{
a = result;
b = int.Parse(tokens[i]);
result = a - b;
i=i+1;
}
else
{
i++;
//a = result;
b = int.Parse(tokens[i]);
result += a - b;
i++;
}
}
return result;
}
It calculated the some basic calculation operations but stuck on above mentioned string operation.I need to return integer value from tokenized string by performing calculations
Can any one please suggest me better solution?
I think you want to perform operation on this string but your operators are in the form of string like minus for - or plus for +.
So basically your string
string expression="1 plus 1 minus 2 plus 2 minus 2 minus 5 plus 10";
should be equivalent to
string myExpression= "1 + 1 - 2 + 2 - 2 - 5 + 10"
and your result should be the math calculation of this ie. 5
For that DataTable.Compute would be handy for you and can try this solution
public int Calculate()
{
string expression = "1 plus 1 minus 2 plus 2 minus 2 minus 5 plus 10";
string mathExpression = expression.Replace("plus", "+").Replace("minus", "-");
DataTable dt = new DataTable();
var value = dt.Compute(mathExpression, "");
return (int)value;
}
You are doing way to much stuff.
The first number is always the starting point, your initial result.
Then you need to loop all tokens by steps on 2.
On each loop, the first item is the operator and the 2nd item is the number.
Depending on the first item [i] you assign the value [i+1] to the result.
// This assume perfect parameter
public int Calculate(string expression)
{
int result = 0;
string[] tokens = null;
tokens = expression.Split(" ");
result = Int32.Parse(tokens[0]);
for (int i = 1; i <= tokens.Length - 1; i += 2) {
if (tokens[i] == "plus")
result += Int32.Parse(tokens[i + 1]);
else if (tokens[i] == "minus")
result -= Int32.Parse(tokens[i + 1]);
}
return result;
}
You can use Linq Aggregate method and try this. Off course, if the expression it's not well formed it may fail.
var expression = "1 plus 1 minus 2 plus 2 minus 2 minus 5 plus 10";
var exp = expression.Split(' ');
var count = 0;
var result = exp.Aggregate(Convert.ToInt32(exp[0]), (acc, next) =>
{
count++;
if (next == "plus")
return acc + Convert.ToInt32(exp[count]);
if (next == "minus")
return acc - Convert.ToInt32(exp[count]);
return acc;
});

Testing if a list of integer is odd or even

Trying to determine if my list of integer is made of odd or even numbers, my desired output is a list of true an/or false. Can I perform the following operation on the list lst or do I need to create a loop? A is the output.
List <int> lst = new List <int>();
A = IsOdd(lst);
You could try using Linq to project the list:
var output = lst.Select(x => x % 2 == 0).ToList();
This will return a new list of bools such that {1, 2, 3, 4, 5} will map to {false, true, false, true, false}.
Just use the modulus
loop through the list and run the following on each item
if(num % 2 == 0)
{
//is even
}
else
{
//is odd
}
Alternatively if you want to know if all are even you can do something like this:
bool allAreEven = lst.All(x => x % 2 == 0);
There's at least 7 different ways to test if a number is odd or even. But, if you read through these benchmarks, you'll find that as TGH mentioned above, the modulus operation is the fastest:
if (x % 2 == 0)
//even number
else
//odd number
Here are a few other methods (from the website) :
//bitwise operation
if ((x & 1) == 0)
//even number
else
//odd number
//bit shifting
if (((x >> 1) << 1) == x)
//even number
else
//odd number
//using native library
System.Math.DivRem((long)x, (long)2, out outvalue);
if ( outvalue == 0)
//even number
else
//odd number
#region even and odd numbers
for (int x = 0; x <= 50; x = x + 2)
{
int y = 1;
y = y + x;
if (y < 50)
{
Console.WriteLine("Odd number is #{" + x + "} : even number is #{" + y + "} order by Asc");
Console.ReadKey();
}
else
{
Console.WriteLine("Odd number is #{" + x + "} : even number is #{0} order by Asc");
Console.ReadKey();
}
}
//order by desc
for (int z = 50; z >= 0; z = z - 2)
{
int w = z;
w = w - 1;
if (w > 0)
{
Console.WriteLine("odd number is {" + z + "} : even number is {" + w + "} order by desc");
Console.ReadKey();
}
else
{
Console.WriteLine("odd number is {" + z + "} : even number is {0} order by desc");
Console.ReadKey();
}
}
--simple codes--
#region odd / even numbers order by desc
//declaration of integer
int TotalCount = 50;
int loop;
Console.WriteLine("\n---------Odd Numbers -------\n");
for (loop = TotalCount; loop >= 0; loop--)
{
if (loop % 2 == 0)
{
Console.WriteLine("Even numbers : #{0}", loop);
}
}
Console.WriteLine("\n---------Even Numbers -------\n");
for (loop = TotalCount; loop >= 0; loop--)
{
if (loop % 2 != 0)
{
Console.WriteLine("odd numbers : #{0}", loop);
}
}
Console.ReadLine();
#endregion

Categories

Resources