Converting fractions to binary string? - c#

To convert an integer value, manually, to binary string you (one technique is to) continuously divide by 2 till the quotient > 0 and append the remainder in reverse order.
string decimalToBinary(int n)
{
string binary = string.Empty;
while (n > 0)
{
// get the LSB
int remainder = n % 2;
// truncate the LSB
n /= 2;
// insert remainder in front
binary = remainder.ToString() + binary;
}
return binary;
}
However, I can't figure out how to convert a fraction (floating point number like for example -0.30), to binary string. More specifically what algorithm should I use. Could anyone suggest an idea?

To convert an integer value, manually
Note that since your input is a an integer which can be negative or zero. But your condition for the while loop is while (n > 0)
Therefore, your code right now cannot handle the situation when the input is 0 (it will return string.Empty) or negative (it will return nothing).
To fix it, you may consider to change your input to uint and make special case for n == 0:
string decimalToBinary(uint n) //note this uint
{
if (n == 0) //special case
return "0";
string binary = string.Empty;
while (n > 0)
{
// get the LSB
uint remainder = n % 2;
// truncate the LSB
n /= 2;
// insert remainder in front
binary = remainder.ToString() + binary;
}
return binary;
}
Or you change it internally:
private string decimalToBinary(int n) {
string binary = string.Empty;
if (n == 0)
return "0";
uint p = (uint)n; //note this cast
while (p > 0) {
// get the LSB
uint remainder = p % 2;
// truncate the LSB
p /= 2;
// insert remainder in front
binary = remainder.ToString() + binary;
}
return binary;
}
Then you should get what you want.

Here is a C++ implementation for fraction to binary conversion:
double frac = .1;
int digits = 1, intpart;
cout <<".";
while (digits < 32 && frac != 0.)
{
frac = frac * 2;
intpart = frac;
frac = frac - intpart;
cout << intpart;
digits++;
}
Output: .0001100110011001100110011001100
or using recursion:
#include <iostream>
using namespace std;
void fractobin(double frac, int digits);
//==========================================================
int main()
{
cout <<".";
fractobin(.1, 1);
return 0;
}
//==========================================================
void fractobin(double frac, int digits)
{
int intpart;
if (digits >=32 || frac==0.)
{
return;
}
else
{
frac = frac * 2;
intpart = frac;
cout << intpart;
fractobin(frac - intpart, ++digits);
return;
}
}

Related

Convert to fraction inches

I need to convert a double value (centimeters) to a fraction value with this format: 3 1/64 (inches). After reading a lot about this and finding algorithms for converting into fractions, I think they are not good for what I need, because my fractions should be in these formats: ?/2, ?/4, ?/8, ?/16, ?/32, ?/64. I have seen conversion tables like this: table. And I think my best solution is to create a key, value list with all values in the table and for each number find the best approximation in the list.
For example: 3.21 cm. = 1.26378 in = 1 in + 0.26378. So, according the table linked, 0.26378 = 17/64. And the final result should be 1 17/64 inches.
So my questions are:
Is a good idea to have a list with the values in the table and find the closest value in order to give the fraction or it is better to create an algorithm for this?
In case it is fine to create a list with the values, how can I find the closest value of a given number in my list?
I suggest using simple math instead of table
private static string ToFraction64(double value) {
// denominator is fixed
int denominator = 64;
// integer part, can be signed: 1, 0, -3,...
int integer = (int) value;
// numerator: always unsigned (the sign belongs to the integer part)
// + 0.5 - rounding, nearest one: 37.9 / 64 -> 38 / 64; 38.01 / 64 -> 38 / 64
int numerator = (int) ((Math.Abs(value) - Math.Abs(integer)) * denominator + 0.5);
// some fractions, e.g. 24 / 64 can be simplified:
// both numerator and denominator can be divided by the same number
// since 64 = 2 ** 6 we can try 2 powers only
// 24/64 -> 12/32 -> 6/16 -> 3/8
// In general case (arbitrary denominator) use gcd (Greatest Common Divisor):
// double factor = gcd(denominator, numerator);
// denominator /= factor;
// numerator /= factor;
while ((numerator % 2 == 0) && (denominator % 2 == 0)) {
numerator /= 2;
denominator /= 2;
}
// The longest part is formatting out
// if we have an actual, not degenerated fraction (not, say, 4 0/1)
if (denominator > 1)
if (integer != 0) // all three: integer + numerator + denominator
return string.Format("{0} {1}/{2}", integer, numerator, denominator);
else if (value < 0) // negative numerator/denominator, e.g. -1/4
return string.Format("-{0}/{1}", numerator, denominator);
else // positive numerator/denominator, e.g. 3/8
return string.Format("{0}/{1}", numerator, denominator);
else
return integer.ToString(); // just an integer value, e.g. 0, -3, 12...
}
Tests
const double cmInInch = 2.54;
// 1 17/64
Console.Write(ToFraction64(3.21 / cmInInch));
// -1 17/64
Console.Write(ToFraction64(-1.26378));
// 3 1/4
Console.Write(ToFraction64(3.25001));
// 3 1/4
Console.Write(ToFraction64(3.24997));
// 5
Console.Write(ToFraction64(5.000001));
// -1/8
Console.Write(ToFraction64(-0.129));
// 1/8
Console.Write(ToFraction64(0.129));
Added display of feet
public static string ToFraction(this double source, int denominator)
{
var divider = denominator;
var inches = (int) Math.Abs(source);
var numerator = (int) ((Math.Abs(source) - Math.Abs(inches)) * divider + 0.5);
while (numerator % 2 == 0 && divider % 2 == 0)
{
numerator /= 2;
divider /= 2;
}
if (divider == numerator)
{
if (source < 0) inches--;
else inches++;
numerator = 0;
}
var feet = Math.DivRem(inches, 12, out inches);
var valueBuilder = new StringBuilder();
if (source + 1d / denominator < 0) valueBuilder.Insert(0, "-");
if (feet > 0)
{
valueBuilder.Append(feet);
valueBuilder.Append("'");
valueBuilder.Append("-");
}
valueBuilder.Append(inches);
if (numerator != 0)
{
valueBuilder.Append(" ");
valueBuilder.Append(numerator);
valueBuilder.Append("/");
valueBuilder.Append(divider);
}
valueBuilder.Append('"');
return valueBuilder.ToString();
}
All tests passed
[TestCase]
public void FractionTest()
{
Assert.AreEqual("0\"", 0d.ToFraction());
Assert.AreEqual("0\"", (-0d).ToFraction());
Assert.AreEqual("0\"", (-0.00001d).ToFraction());
Assert.AreEqual("1\"", 1d.ToFraction());
Assert.AreEqual("-1\"", (-1d).ToFraction());
Assert.AreEqual("0 1/8\"", 0.129.ToFraction());
Assert.AreEqual("-0 1/8\"", (-0.129).ToFraction());
Assert.AreEqual("-1 1/4\"", (-1.26378).ToFraction());
Assert.AreEqual("5\"", 5.000001.ToFraction());
Assert.AreEqual("3 1/4\"", 3.24997.ToFraction());
Assert.AreEqual("3 1/4\"", 3.25001.ToFraction());
Assert.AreEqual("1'-0\"", 12d.ToFraction());
Assert.AreEqual("1'-0 3/32\"", 12.1d.ToFraction());
Assert.AreEqual("1'-1\"", 13d.ToFraction());
Assert.AreEqual("1'-3 1/8\"", 15.125d.ToFraction());
Assert.AreEqual("1'-0\"", 12.00001d.ToFraction());
Assert.AreEqual("-1'-0\"", (-12.00001d).ToFraction());
Assert.AreEqual("-2'-1 7/32\"", (-25.231d).ToFraction());
}
taking the code of Dmitry Bychenko, we need to add the case "else if (denominator == numerator)" if fraction equals to 1 to add 1 if the value is positive or remove 1 if the value is negative (ex denominator/numerator = 64/64)
private static string ToFraction64(double value)
{
// denominator is fixed
int denominator = 64;
// integer part, can be signed: 1, 0, -3,...
int integer = (int)value;
// numerator: always unsigned (the sign belongs to the integer part)
// + 0.5 - rounding, nearest one: 37.9 / 64 -> 38 / 64; 38.01 / 64 -> 38 / 64
int numerator = (int)((Math.Abs(value) - Math.Abs(integer)) * denominator + 0.5);
// some fractions, e.g. 24 / 64 can be simplified:
// both numerator and denominator can be divided by the same number
// since 64 = 2 ** 6 we can try 2 powers only
// 24/64 -> 12/32 -> 6/16 -> 3/8
// In general case (arbitrary denominator) use gcd (Greatest Common Divisor):
// double factor = gcd(denominator, numerator);
// denominator /= factor;
// numerator /= factor;
while ((numerator % 2 == 0) && (denominator % 2 == 0))
{
numerator /= 2;
denominator /= 2;
}
// The longest part is formatting out
// if we have an actual, not degenerated fraction (not, say, 4 0/1)
if (denominator > 1)
if (integer != 0) // all three: integer + numerator + denominator
return string.Format("{0} {1}/{2}", integer, numerator, denominator);
else if (value < 0) // negative numerator/denominator, e.g. -1/4
return string.Format("-{0}/{1}", numerator, denominator);
else // positive numerator/denominator, e.g. 3/8
return string.Format("{0}/{1}", numerator, denominator);
//if fraction equals to 1 we add 1 if the value is positive or remove 1 if the value is negative (ex denominator/numerator = 64/64)
else if (denominator == numerator)
{
if (value < 0) // negative numerator/denominator, e.g. -1/4
integer--;
else // positive numerator/denominator, e.g. 3/8
integer++;
return integer.ToString();
}
else
return integer.ToString(); // just an integer value, e.g. 0, -3, 12...
}
My function is easier and more simple..
It return an array of three integer {Inches, Numerator, Denominator} from a decimal value, the fracBase argument mean the precision as 16, 32, 64, 128 ....
public static int[] GetImpFractions(decimal value, int fracBase = 32)
{
int[] result = { 0, 0, 0 };
result[0] = (int)Math.Truncate(value);
decimal num = (value - (decimal)result[0]);
num *= fracBase;
decimal denom = fracBase;
if (num > 0)
{
while (num % 2 == 0)
{
num /= 2;
denom /= 2;
}
if (num == 1 && denom == 1)
{
result[0] += 1;
num = 0;
denom = 0;
}
result[1] = (int)Math.Truncate(num);
result[2] = (int)Math.Truncate(denom);
}
return result;
}

itoa conversion in C#

It was an interview question asked to me - write itoa conversion without using any builtin functions.
The following is the algorithm I am using. But ('0' + n % 10); is throwing an error:
cannot convert string to int
private static string itoa(int n)
{
string result = string.Empty;
char c;
bool sign = n > 0 ? true : false;
while (true)
{
result = result + ('0' + n % 10); //'0'
n = n / 10;
if(n <= 0)
{
break;
}
}
if(sign)
{
result = result + '-';
}
return strReverse(result);
}
I'm unclear why you'd want to do this; just call ToString on your integer. You can specify whatever formatting you need with the various overloads.
As #minitech commented, we usually just use ToString() to do that in C#. If you really want to write the algorithm on your own, the following is an implementation:
public static partial class TestClass {
public static String itoa(int n, int radix) {
if(0==n)
return "0";
var index=10;
var buffer=new char[1+index];
var xlat="0123456789abcdefghijklmnopqrstuvwxyz";
for(int r=Math.Abs(n), q; r>0; r=q) {
q=Math.DivRem(r, radix, out r);
buffer[index-=1]=xlat[r];
}
if(n<0) {
buffer[index-=1]='-';
}
return new String(buffer, index, buffer.Length-index);
}
public static void TestMethod() {
Console.WriteLine("{0}", itoa(-0x12345678, 16));
}
}
It works only for int. The range int is -2147483648 to 2147483647, the length in the string representation would be max to 11.
For the signature of itoa in C is char * itoa(int n, char * buffer, int radix);, but we don't need to pass the buffer in C#, we can allocate it locally.
The approach that add '0' to the remainder may not work when the radix is greater than 10; if I recall correctly, itoa in C supports up to 36 based numbers, as this implementation is.
('0' + n % 10) results in an int value, so you should cast it back to char. There are also several other issues with your code, like adding - sign on the wrong side, working with negative values, etc.
My version:
static string itoa(int n)
{
char[] result = new char[11]; // 11 = "-2147483648".Length
int index = result.Length;
bool sign = n < 0;
do
{
int digit = n % 10;
if(sign)
{
digit = -digit;
}
result[--index] = (char)('0' + digit);
n /= 10;
}
while(n != 0);
if(sign)
{
result[--index] = '-';
}
return new string(result, index, result.Length - index);
}

Binary to decimal

int rem, count = 0;
long int n=0, b, i;
count << "Enter the Binary value to convert in Decimal = ";
cin >> b;
i = b;
while (b > 0)
{
rem = b % 10;
n = n + rem * pow(2, count);
count++;
b = b / 10;
}
cout << "The decimal value of Binary no. = " << i << " = " << n;
getch();
I made this simple program in C++ and now I want to implement it in C# but I couldn't do so because I don't know how to implement the logic which I used in the loop.
Because in C++ the keyword pow is used to multiply the value of 2 so I don't know how to do it in C#.
No, pow() is not a keyword, it's a function from the standard library's math.h.
You can easily replace it in this case, for both C++ and C#, with bit shifting:
(int) pow(2, count) == 1 << count
The above is true for all positive values of count, up to the limit of the platform's/language's precision.
I believe the problem as a whole is much easier to solve using shifting.
Check this:
int bintodec(int decimal);
int _tmain(int argc, _TCHAR* argv[])
{
int decimal;
printf("Enter an integer (0's and 1's): ");
scanf_s("%d", &decimal);
printf("The decimal equivalent is %d.\n", bintodec(decimal));
getchar();
getchar();
return 0;
}
int bintodec(int decimal)
{
int total = 0;
int power = 1;
while(decimal > 0)
{
total += decimal % 10 * power;
decimal = decimal / 10;
power = power * 2;
}
return total;
}
You have to take care of data types in C#
long int n=0, b, i; // long int is not valid type in C#, Use only int type.
Replace pow() to Math.Pow()
pow(2, count); // pow() is a function in C/C++
((int)Math.Pow(2, count)) // Math.Pow() is equivalent of pow in C#.
// Math.Pow() returns a double value, so cast it to int
Have a look at the Math.Pow Method.
In general, the Math class provides much functionality you are looking for.
A complete code example elsewhere on the internet is enter link description here.
public int BinaryToDecimal(string data)
{
int result = 0;
char[] numbers = data.ToCharArray();
try
{
if (!IsNumeric(data))
error = "Invalid Value - This is not a numeric value";
else
{
for (int counter = numbers.Length; counter > 0; counter--)
{
if ((numbers[counter - 1].ToString() != "0") && (numbers[counter - 1].ToString() != "1"))
error = "Invalid Value - This is not a binary number";
else
{
int num = int.Parse(numbers[counter - 1].ToString());
int exp = numbers.Length - counter;
result += (Convert.ToInt16(Math.Pow(2, exp)) * num);
}
}
}
}
catch (Exception ex)
{
error = ex.Message;
}
return result;
}
http://zamirsblog.blogspot.com/2011/10/convert-binary-to-decimal-in-c.html

How do I check the validity of the Canadian Social Insurance Number in C#?

I've been given the assignment to write an algorithm in C# that checks the validity of a Canadian Social Insurance Number (SIN). Here are the steps to validate a SIN.
Given an example Number: 123 456 782
Remove the check digit (the last digit): 123456782
Extract the even digits (2,4,6,8th digith): 12345678
Double them:
2 4 6 8
| | | |
v v v v
4 8 12 16
Add the digits together: 4+8+1+2+1+6 = 22
Add the Odd placed digits: 1+3+5+7 = 16
Total : 38
Validity Algorithm
If the total is a multiple of 10, the check digit should be zero.
Otherwise, Subtract the Total from the next highest multiple of 10 (40 in this case)
The check digit for this SIN must be equal to the difference of the number and the totals from earlier (in this case, 40-38 = 2; check digit is 2, so the number is valid)
I'm lost on how to actually implement this in C#, how do I do this?
This is a nice problem to solve. This should be more efficient than converting to string and parsing back to integer. This solution will work on .NET 3.5 and later.
public static IEnumerable<int> ToDigitEnumerable(this int number)
{
IList<int> digits = new List<int>();
while(number > 0)
{
digits.Add(number%10);
number = number/10;
}
//digits are currently backwards, reverse the order
return digits.Reverse();
}
public static bool IsCanadianSocialInsuranceNumber(int number)
{
var digits = number.ToDigitEnumerable();
if (digits.Count() != 9) return false;
//The left side of the addition is adding all even indexes (except the last digit).
//We are adding even indexes since .NET uses base 0 for indexes
//The right side of the addition, multiplies the odd index's value by 2, then breaks each result into
//individual digits, then adds them together
var total = digits.Where((value, index) => index%2 == 0 && index != 8).Sum()
+ digits.Where((value, index) => index%2 != 0).Select(v => v*2)
.SelectMany(v => v.ToDigitEnumerable()).Sum();
//The final modulous 10 operator is to handle the scenarios where the total
//is divisble by 10, in those cases, the check sum should be 0, not 10
var checkDigit = (10 - (total%10)) % 10;
return digits.Last() == checkDigit;
}
One problem with this solution is that it assumes that number, represented as an integer, is 9 digits (can't start with a 0). If the number can start with a 0, then it has to be represented as a string (or converted to a string and padding with zeros). The logic to test will remain mostly intact, but the parts that assume integers will need to be swapped out with strings, and then you'll have to do parsing.
The specification you were given makes things a bit more complicated than they need to be: it's actually equivalent and simpler to just add the last digit into the checksum and make sure the checksum's last digit is 0.
The usual trouble new programmers have is "how do I get each digit?" Here's how:
In integer types, % 10 will delete everything but the last digit of the number: 123 % 10 == 3, and / 10 will delete the last digit of the number: 123 / 10 == 12.
In strings, str[i] - '0' will give you the digit at index i. The characters for digits are stored as special numbers: '0' is stored as 48 and '9' is stored as 57. If you subtract 48, you'll have the actual digit as a number. You don't really need to memorize "subtract 48", of course: if you just subtract '0', it will do the same thing: '8' - '0' == 8
Here are two efficient methods. One takes an int and checks the checksum of the SIN. One takes a string and checks both the format (must be "ddd ddd ddd") and the checksum of the SIN; though it's pretty efficient, it is a bit ugly and repetitive.
// Checks that the given int is a valid Canadian Social Insurance Number
// according to both range (000 000 000 to 999 999 998) and checksum.
public static bool IsValidSIN(int sin) {
if (sin < 0 || sin > 999999998) return false;
int checksum = 0;
for (int i = 4; i != 0; i--) {
checksum += sin % 10;
sin /= 10;
int addend = 2*(sin % 10); if (addend >= 10) addend -= 9;
checksum += addend;
sin /= 10;
}
return (checksum + sin) % 10 == 0;
}
// Checks that the given string is a valid Canadian Social Insurance Number
// according to both format ("ddd ddd ddd") and checksum.
// Implementation note: uses an admittedly ugly and repetitive parser.
public static bool IsValidSIN(string sin) {
if (sin.Length != 11) return false;
int checksum, addend;
checksum = sin[0] - '0';
if (checksum < 0 || checksum > 9) return false;
addend = 2*(sin[1] - '0'); if (addend >= 10) addend -= 9;
if (addend < 0 || addend > 9) return false;
checksum += addend;
addend = sin[2] - '0';
if (addend < 0 || addend > 9) return false;
checksum += addend;
if (sin[3] != ' ') return false;
addend = 2*(sin[4] - '0'); if (addend >= 10) addend -= 9;
if (addend < 0 || addend > 9) return false;
checksum += addend;
addend = sin[5] - '0';
if (addend < 0 || addend > 9) return false;
checksum += addend;
addend = 2*(sin[6] - '0'); if (addend >= 10) addend -= 9;
if (addend < 0 || addend > 9) return false;
checksum += addend;
if (sin[7] != ' ') return false;
addend = sin[8] - '0';
if (addend < 0 || addend > 9) return false;
checksum += addend;
addend = 2*(sin[9] - '0'); if (addend >= 10) addend -= 9;
if (addend < 0 || addend > 9) return false;
checksum += addend;
addend = sin[10] - '0';
if (addend < 0 || addend > 9) return false;
return (checksum + addend) % 10 == 0;
}
I don't know C# but here is a solution in Python. Maybe you can learn from it the method of how to implement it in C#.
def check(SIN):
SIN = ''.join(SIN.split(' '))
if len(SIN) != 9:
raise ValueError("A Canadian SIN must be 9 digits long")
check_digit = int(SIN[-1])
even_digits = [int(SIN[i]) for i in range(1,8,2)]
odd_digits = [int(SIN[i]) for i in range(0,8,2)]
total = sum(i/10 + i%10 for i in map(lambda x: 2*x, even_digits)) + sum(odd_digits)
if total%10 == 0:
return check_digit == 0
else:
return ((total/10)+1)*10 - total == check_digit
if __name__ == '__main__':
for SIN in ['123 456 782',
'123 456 789',
'046 454 286']:
print '%s is %sa valid Canadian SIN' % (SIN, '' if check(SIN) else 'NOT ')
which outputs:
123 456 782 is a valid Canadian SIN
123 456 789 is NOT a valid Canadian SIN
046 454 286 is a valid Canadian SIN
Search on the internet for "Luhn algorithm". You'll find a lot of examples.
The crux of the program is that you need to have some way of iterating over each integer in the SIN.
Since the easiest way is to convert the integer to a string for manipulation operations and back to an integer for addition/multiplication operations, I used the following approach:
The Program:
public class Program
{
static void Main(string[] args)
{
int sn = 123456782;
int[] Digits;
int AddedResult = 0;
string s = sn.ToString();
string sa = s.Substring(s.Length - 1, 1);
int checkDigit = Convert.ToInt32(sn.ToString().Substring(s.Length - 1, 1));
//get the last digit.
if (IsValidLength(sn))
{
sn = RemoveLastDigit(sn);
Digits = ExtractEvenDigits(sn);
Digits = DoubleDigits(Digits);
AddedResult = AddedEvenDigits(Digits);
AddedResult += AddOddDigits(sn);
if (IsValidSN(AddedResult, checkDigit))
{
Console.WriteLine("The number is valid");
}
else
{
Console.WriteLine("The Number is not valid");
}
}
else
{
Console.WriteLine("NotValidLength");
}
Console.Read();
}
public static bool IsValidSN(int AddedResult, int checkDigit)
{
return ((AddedResult % 10 == 0 && checkDigit == 0) || IsValidDifference(AddedResult, checkDigit));
}
public static bool IsValidDifference(int AddedResult, int checkDigit)
{
int nextHighestTens = AddedResult;
while (nextHighestTens % 10 != 0)
{
nextHighestTens++;
}
return ((nextHighestTens - AddedResult) == checkDigit);
}
public static int AddOddDigits(int sn)
{
string s = sn.ToString();
int i = 1;
int addedResult = 0;
foreach (char c in s)
{
if (i % 2 != 0)
{
addedResult += Convert.ToInt32(c.ToString());
}
i++;
}
return addedResult;
}
public static int AddedEvenDigits(int[] Digits)
{
int addedEvenDigits = 0;
string s = "";
for (int i = 0; i < Digits.Length; i++) //extract each digit. For example 12 is extracted as 1 and 2
{
s += Digits[i].ToString();
}
for (int i = 0; i < s.Length; i++) //now add all extracted digits
{
addedEvenDigits += Convert.ToInt32(s[i].ToString());
}
return addedEvenDigits;
}
public static int[] DoubleDigits(int[] Digits)
{
int[] doubledDigits = new int[Digits.Count()];
for (int i = 0; i < Digits.Length; i++)
{
doubledDigits[i] = Digits[i] * 2;
}
return doubledDigits;
}
public static int[] ExtractEvenDigits(int sn)
{
int[] EvenDigits = new int[4];
string s = sn.ToString(); //12345678
int j = 0;
for (int i = 1; i < s.Length; i += 2)
{
EvenDigits[j] = Convert.ToInt32(s[i].ToString());
j++;
}
return EvenDigits;
}
public static int RemoveLastDigit(int sn)
{
string s = sn.ToString();
return Convert.ToInt32(s.Substring(0, s.Count() - 1));
}
public static bool IsValidLength(int sn)
{
return (sn > 9999999 && sn < 1000000000);
}
}
I wrote this in about 20 minutes, so it's not really worthy to turn in. I plan on improving it as an exercise, and I wrote some unit tests for it (that I plan on making better).
[TestFixture]
public class SINTests
{
private int SinNumber = 123456782;
[Test]
public void TestValidNumber()
{
Assert.IsTrue(Program.IsValidLength(SinNumber));
}
[Test]
public void TestRemoveLastDigit()
{
Assert.AreEqual(12345678, Program.RemoveLastDigit(SinNumber));
}
[Test]
public void TestExtractEvenDigit()
{
int sn = 12345678;
int[] array = new int[] { 2,4,6,8 };
Assert.AreEqual(array, Program.ExtractEvenDigits(sn));
}
[Test]
public void TestAddOddDigits()
{
int sn = 12345678;
int result = 1 + 3 + 5 + 7;
Assert.AreEqual(result, Program.AddOddDigits(sn));
}
[Test]
public void TestDoubleEvenDigits()
{
int sn = 12345678;
int[] original = new int[] { 2, 4, 6, 8 };
int[] array = new int[] { 4, 8, 12, 16 };
Assert.AreEqual(array, Program.DoubleDigits(original));
}
[Test]
public void TestOddDigits()
{
int sn = 12345678;
Assert.AreEqual(16, Program.AddOddDigits(sn));
}
}
Since a string can be construed as an Array of Characters1, the operations that work on a string also need to be aware of the fact that Converting a character to an integer is different than converting a string to an integer. For instance:
Char c = '2';
int cInt = Convert.ToInt32(c); // returns 50
string s = c.ToString();
int sInt = Convert.ToInt32(s) //returns 2;
1Technically, a string is not an array of Characters in C# (though it is in C and C++), but because you can access the components of a string through an indexer, it can be treated like an array of characters.
I also recently coded this into an application. Before calling this, the string sSIN has already been checked through regex for being a 9-digit number.
public static bool IsCanadianSocialInsuranceNumber(string sSIN)
{
int iChecksum = 0;
int iDigit = 0;
for (int i = 0; i < sSIN.Length; i++)
{
// even number else odd
if (((i+1) % 2) == 0)
{
iDigit = int.Parse(sSIN.Substring(i, 1))*2;
iChecksum += (iDigit < 10) ? iDigit : iDigit - 9;
}
else
{
iChecksum += int.Parse(sSIN.Substring(i, 1));
}
}
return ((iChecksum % 10) == 0) ? true : false;
}
Here's a very simple way:
int test = 123456782;
if(test > 100000000 && test < 999999999)
{
int check = test % 10;
string temp = "";
foreach(char c in test.ToString().Substring(0, 8))
{
//The character codes for digits follow the same odd/even pattern as the digits.
//This code puts each digit or its value times 2, into a string and sums the digits
//after instead of keeping 2 separate totals
if(c % 2 == 1)
{
temp += c;
}
else
{
temp += (int.Parse(c.ToString()) * 2).ToString();
}
}
int temp2 = temp.Sum((x => int.Parse(x.ToString())));
//no need to compare the sum to the next 10, the modulus of 10 will work for this
int temp2mod = temp2 % 10;
if((temp2mod == 0 && temp2mod == check) || (10 - temp2mod == check))
return true;
}
return false;
public bool ValidateSIN(string sin)
{
if ((int)Char.GetNumericValue(sin[0]) == 0)
{
return false;
}
else
{
string evenString = "";
int totalOfEvens = 0;
int totalOfOdds = 0;
int total, nextMultipleOfTen, remainder;
int checkDigit = (int)Char.GetNumericValue(sin[8]);
// multiply each even number of the input string by 2
// get the resulting numbers into a string so the chars
// can be manipulated as individual digits
for (int i = 1; i <= 7; i += 2)
{
evenString += (Char.GetNumericValue(sin[i]) * 2);
}
// add the individual digits of the products from the above loop
foreach (char c in evenString)
{
totalOfEvens += (int)Char.GetNumericValue(c);
}
// get the odd numbers of the input string, minus the last number,
// and add them together
for (int i = 0; i <= 6; i += 2)
{
totalOfOdds += (int)Char.GetNumericValue(sin[i]);
}
total = totalOfEvens + totalOfOdds;
// take the quotient of total divided by 10 and add 1 to get the next multiple of ten
nextMultipleOfTen = (Math.DivRem(total, 10, out remainder) + 1) * 10;
if ((total % 10 == 0 && checkDigit == 0) || (checkDigit == nextMultipleOfTen - total))
{
return true;
}
else
{
return false;
}
}
}
Fastest method I've tried so far. No LINQ, no if/else, no odd/even checks, only 1 loop to get an array of integers from the string.
Caveat: no guards - input is assumed to be a string of 9 numbers.
public static bool IsValidSin(string input)
{
int[] luhnMap = { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 };
int[] ints = new int[9];
for (int i = 0; i < 9; i++)
{
ints[i] = int.Parse(input[i].ToString());
}
int check = ints[0] + luhnMap[ints[1]] + ints[2] + luhnMap[ints[3]] + ints[4] + luhnMap[ints[5]] + ints[6] + luhnMap[ints[7]] + ints[8];
return (check % 10) == 0;
}

How to convert a column number (e.g. 127) into an Excel column (e.g. AA)

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
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;
}
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))
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;
}

Categories