Convert characters string to Unsigned int

Go To StackoverFlow.com

1

I need to send a request to a quote server. Each request should have a distinctive request number (unsigned int) so that when quotes returned with that attached request number I will know to which symbol those quotes belong. Is there any special chars encoding for this type of cases ? E.g. "A" is 13 and "B" is 14, so for "BA" symbol my request number will be 1413.

2012-04-03 21:20
by Vitaly
Are the quotes stock symbols? (I'm asking because that defines the range of symbols and maximum length of the quote string) - Eric J. 2012-04-03 21:24
Yes, they are stock and futures so apart from letters there will be one more symbol "/" - Vitaly 2012-04-03 21:27
What is the maximum length of a symbol - phoog 2012-04-03 21:34
If it is FOREX symbol then 7 ("EUR/USD"). That's maximum - Vitaly 2012-04-04 00:07
@Vitaly the approach in the accepted answer will overflow the value of a Uint32 for symbols longer than 5 characters. This will make reversing the calculation more complicated than it needs to be. Also, with a set of 27 symbols, there are more possible 7-symbol combinations than there are values of UInt32, so no generalized solution will work - phoog 2012-04-04 14:59


2

Will the characters always be capitals A-Z? If so, something simple like this will convert it in the manner that you've described:

var symbol = "BA";
var encoded = symbol.Aggregate(0u, (acc, c) => (uint)(acc * 100 + c - 'A' + 13));
2012-04-03 21:24
by porges
That doesn't provide a mapping to uint as requested by the OP - Eric J. 2012-04-03 21:25
Whoops, missed that the result should be a uint and not a string. Changed that : - porges 2012-04-03 21:29
@Vitaly: Note that this doesn't do any handling for the "/" character you mentioned. I'm not sure what value you want it to have, but the way the code is at the moment, it probably won't do nice things : - porges 2012-04-04 05:26
@Vitaly, this also fails for symbols over 5 characters in length, since the Uint32.MaxValue is a 10-digit value - phoog 2012-04-04 14:52


3

As for mapping the chars directly to a uint, can you guarantee that the symbols are 6 characters or fewer? If not, then there are more possible symbol values than possible uint values.

In any event, the point of a request number is not to encode information about the request; rather, you should keep a dictionary of request numbers (as keys) and information about what to do with the response (as values). With your approach, if you have more than one request for the same symbol, you would end up with different requests that share the same request number.

For example, if you want to map the response to a symbol, you could do this:

private Dictionary<uint, string> _requests = new Dictionary<int, string>();
private uint _requestNumber = 0;

void SendRequest(string symbol)
{
    uint currentRequestNumber = _requestNumber++;
    _requests[currentRequestNumber] = symbol;
    //... send request using currentRequestNumber
}

void ReceiveResponse(Response response)
{
    string symbol = _requests[response.RequestNumber];
    _requests.Remove(response.RequestNumber);
    //...do something with the response...
}

This is not thread safe; it's just a sketch to illustrate the idea.

To answer the question as asked, if the range of possible symbol values is small enough, you could take the approach you outline in your question, where each character maps to a 2-digit number, and you simply concatenate these numbers. I'm not aware of an existing system that uses this approach.

This approach wastes many uint values that cannot correspond to any symbol. For example, if A is 10, and Z is 35, and \ is 36, then these ranges are wasted: 0 to 9, 37-1009, 1037-1109, etc.

Another option would be to interpret the symbol as a base-27 number (with 'A' to 'Z' plus '\' as valid digits) and convert it to base 10.

If you would like some sample code, please give some more information about the range of possible symbol values.

2012-04-03 21:27
by phoog
And if you care about consistency of the mapping from the number to the symbol over time, what then - Eric J. 2012-04-03 21:31
@EricJ. the main point is that you probably should not care about that. If you do care about it, then you need to keep a dictionary of symbols or develop a mapping function like the OP is asking for - phoog 2012-04-03 21:36
Very good idea. Made me think. Thank you very much - Vitaly 2012-04-04 00:49
@phoog: If you don't care about consistency over time, then just use mySymbol.GetHashCode() :- - Eric J. 2012-04-04 02:27
@EricJ. that also fails to distinguish separate requests for the same symbol; this approach is intended to maintain that distinction - phoog 2012-04-04 14:54


1

Assuming A = 13, B = 14, ..., Z = 38

you can write a simple function that does this conversion for you. Something like:

uint output = 0;
foreach (char c in inpStr) {
    output = output * 100 + (13 + c - 'A');
}
return output;

Where inpStr = "BA" in your example.

2012-04-03 21:28
by K Mehta


1

If your symbols are always upper case letters, you can create a mapping something like this:

uint result = 0;
uint power = 1;

for (int i=0; i < input.Length; i++)
{
  uint digitValue = power * (input[i] - 'A');
  result += digitValue;
  power *= 26;
}

This effectively considers your symbol to be a base-26 number (digits are 'A' through 'Z') and converts it to base-10, with the "ones" digit furthest to the left (reverse of standard numbers, but irrelevant because it's internally consistent). If you wanted to treat the digits as ones-digit-on-the-left, you would just need to modify input[i] to be input[input.Length - i].

Update Given your clarification that the '/' symbol is also allowed, just convert the "base" from 26 to 27 and order "/" just above "Z" (arbitrary, but easier). You will need to test if input[i] is '/' and assign the result power * 27 for that case.

2012-04-03 21:28
by Eric J.