7

What is the fastest way to convert int to char? I need a faster way because,

convertingchar = Convert.ToChar(intvalue);

is my slowest part in the program. I have multiple different int values, that have to be converted to char. My project is very big and I can't post my function. That's why I post this test function.

My Code so far.

char convertingchar = ' ';
...some code...
public void convert(int intvalue){
   convertingchar = Convert.ToChar(intvalue);
}
  • What makes you think you need a faster way than that? – Ant P Mar 13 '15 at 10:05
  • 3
    How did you profile it? – JustSomeGuy Mar 13 '15 at 10:05
  • just use `char c = (char)32;` which gives you a space ;) – Icepickle Mar 13 '15 at 10:05
  • One step would be to avoid an extra wrapper method call and just call `Convert.ToChar` directly. – CyberDude Mar 13 '15 at 10:06
  • 5
    `Convert.ToChar` eventually performs an explicit conversion as `(char)value`, where `value` is your `int` value. Before doing so, it checks to ensure `value` is in the range `0 to 0xffff`, and throws an `OverflowException` if it is not. The extra method call, value/boundary checks, and `OverflowException` may be useful, but if not, the performance will be better if you just use `(char)value`. – Mahesh Mar 13 '15 at 10:06
  • 1
    I think I need a faster way than that, because after Perfomance testing in Visual studio this is my slowest part. Remember this is a test function. I just thought maybe there is a faster way to convert. –  Mar 13 '15 at 10:06
  • something like `unchecked((char)someInt)` – JustSomeGuy Mar 13 '15 at 10:07
  • May be it simply being called many times, but not slower. – VMAtm Mar 13 '15 at 10:07
  • @CoderofCode could you write an answer for me please I think you are right :) –  Mar 13 '15 at 10:09
  • 1
    @CyberDude remember this is a testfunction in my real project the funtion is more complex I just want to extract my problem –  Mar 13 '15 at 10:10
  • 3
    If this is the most time consuming part of your program you might want to find a way of not converting each char separately or prevent the need of so many conversions – Emond Mar 13 '15 at 10:10
  • Are you sure you do not want to just [convert byte\[\]to string](http://stackoverflow.com/questions/1003275/how-to-convert-byte-to-string)? – PTwr Mar 13 '15 at 13:57
  • I am not sure, but I implemented the solution from @CoderofCode and its good –  Mar 13 '15 at 14:33

3 Answers3

20

Running a quick performance test between your Convert.ToChar approach and the mentioned casting one, I find that 65535 tests (char.MaxValue):

Convert: 00:00:00.0005447 total
Cast:    00:00:00.0003663 total

At its best, cast was running for me in about half the time of convert.

The implementation of Convert.ToChar as found in Reference Source reveals the time consumer:

public static char ToChar(int value) {
    if (value < 0 || value > Char.MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_Char"));
    Contract.EndContractBlock();
    return (char)value;
}

While these checks do certainly serve a purpose, your particular use-cases, especially in such a performance-critical situation, may not require them. That's up to you.

A nice alternative to enforce these checks would be to use a ushort rather than an int. Obviously that may or may not be attainable, but with the same maximum value, this means you'll get compile-time checking for what you were previously depending on ToChar to perform.

David says Reinstate Monica
  • 19,209
  • 22
  • 79
  • 122
Matthew Haugen
  • 12,916
  • 5
  • 38
  • 54
  • 3
    You can't understate the use of `ushort` here - it will make any boundary checks irrelevant, thus getting you speed and accuracy. – Trenin Mar 13 '15 at 18:14
  • 3
    @Trenin - while what you say is true, any effort you go to in order to supply the function with `ushort` instead of `int`, would be better served by creating `char` instead of either `int`, or `ushort`, and then not calling a `char ToChar(char)` function completely.... In other words, either he has ints and can't change that, or he can change that, and then should change to `char`, not `ushort` – rolfl Mar 13 '15 at 19:15
17

Convert.ToChar eventually performs an explicit conversion as (char)value, where value is your int value. Before doing so, it checks to ensure value is in the range 0 to 0xffff, and throws an OverflowException if it is not. The extra method call, value/boundary checks, and OverflowException may be useful, but if not, the performance will be better if you just use (char)value.

This will make sure everything is ok while converting but take some time while making sure of that,

convertingchar = Convert.ToChar(intvalue);

This will convert it without making sure everything is ok so less time,

convertingchar = (char)intvalue;

For example.

 Console.WriteLine("(char)122 is {0}", (char)122);

yields:

(char)122 is z


NOTE

Not related to question directly but if you feel that Conversion is slow then you might be doing something wrong. The question is why do you need to convert the lot of the int to char. What you are trying to achieve. There might be better way.

Mahesh
  • 8,694
  • 2
  • 32
  • 53
8

The fastest way, contrary to what the others have noted is to not run any code at all. In all the other cases, there is memory allocated for the int and memory allocated for the char. Thus the best that can be achieved is simply copy the int to the char address.

However this code is 100% faster, since no code is run at all.

[StructLayout(LayoutKind.Explicit)]
public struct Foo
{
    [FieldOffset(0)] 
    public int Integer;
    [FieldOffset(0)] 
    public char Char;
}

https://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
Aron
  • 15,464
  • 3
  • 31
  • 64
  • Though you will need to run code to move the values to and from those fields. – Lasse V. Karlsen Mar 13 '15 at 10:49
  • how are you now able to convert? –  Mar 13 '15 at 10:50
  • Move an integer into the Integer field, and grab the character from the Char field. – Lasse V. Karlsen Mar 13 '15 at 10:51
  • @LasseVKarlsen yes you would need to have code move the value into Integer. In this case you gain nothing. But if you integrate the fields into the objects that read or write the values, then you can skip a single copy... – Aron Mar 13 '15 at 10:58
  • 3
    Your code is not portable, as it's effect depends on endianness (unless C# unifies that somehow, which is at least unlikely), and shouldn't make any difference for optimized performance (unless optimization is really bad). – Frax Mar 13 '15 at 13:04
  • @Frax the question is on pure perf. Otherwise I would agree. – Aron Mar 13 '15 at 13:06
  • @Aron True. But conversion doesn't yield any code itself. In optimized program using cast should give exactly the same result as using your "union" code. Using struck may give even worse effect, if `struct` is treaten differently than `int` in some contexts, like passing arguments (afair some c++ compilers pass struct always by pointer, even if it is small). – Frax Mar 13 '15 at 13:14
  • @Frax yup. Bliting is dangerous and of limited value. But it can work. – Aron Mar 13 '15 at 13:16
  • "In all the other cases, there is memory allocated for the int and memory allocated for the char." false, casting is a 0 opcode operation. – Steve Cox Mar 13 '15 at 16:39
  • At some point you will need to run code to use this. I find the claim "100% faster" BS, as it will take *some* amount of time to convert, if nothing more than copying data. There is no valid proof that this is any faster than a simple cast. –  Mar 13 '15 at 19:34
  • @Thebluefish, no, no code is needed. The solution here is an ungodly hack that takes advantage of the fact that, in a little-endian system, the first byte of an `int` value is a valid `char`. If you convince your compiler that the same memory location represents both an `int` and a `char`, as is done in this struct, you get int->char conversion for free. (You also get the risk that a future maintenance programmer will demand your head on a platter, but that's not a performance issue.) – Mark Mar 13 '15 at 21:25
  • @mark that's cool. So tell me, does this person just magically put this code somewhere and it magically works? Or does he need to *gasp* do something with it? Assuming the person starts with an int, as per the question, there is still code involved to place said int into this struct. Code that will take time to run. –  Mar 13 '15 at 21:53
  • @Thebluefish, the person replaces every declaration of `int` that they want to make convertible with `Foo`. For example, `public void convert(int intvalue)` becomes `public void convert(Foo intvalue)`, and the integer in `intvalue` can immediately be used as if it were a `char`. – Mark Mar 13 '15 at 21:57