6

I am trying to explicity cast an int into a ushort but am getting the Cannot implicity convert type 'int' to 'ushort'

ushort quotient = ((12 * (ushort)(channel)) / 16);

I am using .Net Micro framework so BitConverter is unavailable. Why I am using ushort in the first place has to do with how my data is being sent over SPI. I can understand this particular error has been brought up before on this site but I cannot see why when I am explicity declaring that I dont care if any data goes missing, just chop the 32 bit into a 16 bit and I will be happy.

            public void SetGreyscale(int channel, int percent)
    {
        // Calculate value in range of 0 through 4095 representing pwm greyscale data: refer to datasheet, 2^12 - 1
        ushort value = (ushort)System.Math.Ceiling((double)percent * 40.95);

        // determine the index position within GsData where our data starts
        ushort quotient = ((12 * (ushort)(channel)) / 16); // There is 12 peices of 16 bits

I would prefer not to change int channel, to ushort channel. How can I solve the error?

Michael
  • 83
  • 1
  • 1
  • 6

2 Answers2

11

(ushort) channel is ushort but 12 * (ushort)(channel) would be int, do this instead:

ushort quotient = (ushort) ((12 * channel) / 16);
King King
  • 61,710
  • 16
  • 105
  • 130
  • Thank you very much, this has solve the problem. I guess this means that because 12 is an int that was causing the problem, or was it also the extra brackets? Either case the problem has been solved and Im very happy so thank you. – Michael Sep 14 '13 at 18:34
  • @Michael yes, that's because the `12` is `int`, so the result will be automatically casted to the *higher and bigger* type. – King King Sep 14 '13 at 18:50
  • 1
    @Michael - note that King's statement is not exactly true - the reason you are getting `int` result is lack of `ushort*ushort` operation - there is only `int*int` and `long*long`, so even `((ushort)12)*((ushort)channel)` will be `int`. Same true for all other (+,-, /...). – Alexei Levenkov Sep 14 '13 at 19:36
  • @AlexeiLevenkov it's a shame for me to know that, I didn't think that's the problem, however the same rule (I mentioned) is applicable for the case such as `int` and `long` (`int * long` -> `long`). In fact I learned this rule when learning c++, not c#, there may be some difference here between the two. – King King Sep 15 '13 at 01:24
4

Multiplication of any int and smaller types produces int. So in your case 12 * ushort produces int.

ushort quotient = (ushort)(12 * channel / 16);

Note that above code is not exactly equivalent to original sample - the cast of channel to ushort may significantly change result if value of channel is outside of ushort range (0.. 0xFFFF). In case if it is important you still need inner cast. Sample below will produce 0 for channel=0x10000 (which is what original sample in question does) unlike more regular looking code above (which gives 49152 result):

ushort quotient = (ushort)((12 * (ushort)channel) / 16); 
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • How does `(ushort)channel` help on the 2nd statement? I'd think the type conversion wouldn't happen until after the math operations due to the parenthesis. – jmstoker Sep 14 '13 at 05:49
  • @jmstoker try with `int channel = 0x10000` - first one will multiple as `int` and produce `49152`, but second will cast `0x10000` to `ushort` first producing `0` (and resulting expression is `0`). Note that it may not be what OP wants, but the cast in original post makes expression different from first one I show. – Alexei Levenkov Sep 14 '13 at 05:56
  • That's what I figured would happen. Your answer is misleading. It would be more clear if you added your comment above to your answer and emphasized that casting `channel` in the 2nd statement is not the best thing to do? – jmstoker Sep 14 '13 at 06:17
  • @jmstoker - I've edited answer... I'm not sure what you mean "casting channel in the 2nd statement is *not the best thing to do*" - it produces different result which may or may not be what OP wants - but I see no reason to judge if it is better. Also note that similar can be said about possibility to divide both `12` and `16` by `4` again producing same results for small numbers and drastically different for large ones... Finite numeric types are just pain to deal with - long live `BigInteger` :) – Alexei Levenkov Sep 14 '13 at 06:47
  • You're right, I shouldn't judge the original intent, and thank you for updating your post. I come from the embedded world and there are few situations when you want a cast to result in zero. – jmstoker Sep 14 '13 at 06:56
  • The solution from King solved the problem but this helps explain why it worked that way, thank you for explaining about multiplication of an int with a smaller type. I will avoid that in the future. – Michael Sep 14 '13 at 18:37