Byte overflow evaluate to zero instead of exception? - c#

static void Main(string[] args)
{
int n;
byte b;
n = 256;
b = (byte) n;
Console.WriteLine(b); //0
}
C# byte range is 0 to 255 and hence I try to cast an int of 256 to byte and see what will happen.
Surprisingly it returns 0 instead of 255 or better yet give me an overflow exception?
UPDATES:
I'm trying it on macos which is Mono, if it matters and .NET Framework 4.7

That is the expected behaviour. If you think about it, 256 is one "1" followed by 8 zeroes in binary. When you take away everything except the least significant 8 bits, you get 8 zeroes, which is the value 0.
From the C# language specification §6.2.1:
For a conversion from an integral type to another integral type, the
processing depends on the overflow checking context (§7.6.12) in which
the conversion takes place:
In a checked context, the conversion succeeds if the value of the source operand is within the range of the destination type, but throws
a System.OverflowException if the value of the source operand is
outside the range of the destination type.
In an unchecked context, the conversion always succeeds, and proceeds as follows.
If the source type is larger than the destination type, then the source value is truncated by discarding its “extra” most significant
bits. The result is then treated as a value of the destination type.
If you want an exception, you can used checked:
b = checked((byte) n);

I would like to complement the previous answer.
Take a look at this:
255 -> 11111111 +
001 -> 00000001
256 -> 100000000
As you can see. We have 256 in binary format, but as your number is eight bits, 1 can't be stored. This leave the number 00000000 which is zero.
This is more theory than C# specific question. But i think this is important to understand.

Related

How -128 fits in a sbyte

As I remember we had learned that signed integer types (sbyte, short, int , long)
the first bit is for the sign and the latter 7 bit is for the value.
I saw that sbyte range is -128 to 127 while I thought it must be -127 to 127.
I tried some codes to understand how this is possible and I faced two strange things:
1- I tried the following code:
sbyte a = -128;
Console.Write(Convert.ToString(a, 2));
and the resutl was
1111111100000000
As if its a two byte variable.
2-Tried converting all numbers in the range to binary:
for(sbyte i=-128;i<=127;i++)
{
Console.WriteLine(Convert.ToString(i, 2));
if(i==127) break;
}
If I omit the if(i==127) break; the loop goes on. and with the break, the code in the loop does not execute, some how as if -128 is greater than 127.
My Conclusion:
As I thought that -128 must not fit in a unsigned byte variable and the first and second tries approves that (111111110000000 > 01111111)
but If it does not fit, then why range is -128 to 127?
I saw that sbyte range is -128 to 127 while I thought it must be -127 to 127.
The range is [-128, +127] indeed. The range [-127, +127] would mean that sbyte can represent only 255 different values, while 8 bits make 256 combinations.
And BTW if -128 would not be a legal value, compiler would complain about
sbyte a = -128;
There is no overload Convert.ToString(sbyte value, int toBase), so in your case Convert.ToString(int value, int toBase) is called, and sbyte is promoted to int.
To quickly check the value, you can print sbyte as a hexadecimal number:
sbyte s = -1;
Console.WriteLine("{0:X}", s); // FF, i.e. 11111111
If I omit the if(i==127) break; the loop goes on.
Sure, sbyte.MaxValue is 127, so i<=127 is always true. When i is 127 and gets incremented, an overflow occurs and the next value is -128.

Difference between two large numbers C#

There are already solutions to this problem for small numbers:
Here: Difference between 2 numbers
Here: C# function to find the delta of two numbers
Here: How can I find the difference between 2 values in C#?
I'll summarise the answer to them all:
Math.Abs(a - b)
The problem is when the numbers are large this gives the wrong answer (by means of an overflow). Worse still, if (a - b) = Int32.MinValue then Math.Abs crashes with an exception (because Int32.MaxValue = Int32.MinValue - 1):
System.OverflowException occurred
HResult=0x80131516
Message=Negating the minimum value of a twos complement number is
invalid.
Source=mscorlib
StackTrace: at
System.Math.AbsHelper(Int32 value) at System.Math.Abs(Int32 value)
Its specific nature leads to difficult-to-reproduce bugs.
Maybe I'm missing some well known library function, but is there any way of determining the difference safely?
As suggested by others, use BigInteger as defined in System.Numerics (you'll have to include the namespace in Visual Studio)
Then you can just do:
BigInteger a = new BigInteger();
BigInteger b = new BigInteger();
// Assign values to a and b somewhere in here...
// Then just use included BigInteger.Abs method
BigInteger result = BigInteger.Abs(a - b);
Jeremy Thompson's answer is still valid, but note that the BigInteger namespace includes an absolute value method, so there shouldn't be any need for special logic. Also, Math.Abs expects a decimal, so it will give you grief if you try to pass in a BigInteger.
Keep in mind there are caveats to using BigIntegers. If you have a ludicrously large number, C# will try to allocate memory for it, and you may run into out of memory exceptions. On the flip side, BigIntegers are great because the amount of memory allotted to them is dynamically changed as the number gets larger.
Check out the microsoft reference here for more info: https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx
The question is, how do you want to hold the difference between two large numbers? If you're calculating the difference between two signed long (64-bit) integers, for example, and the difference will not fit into a signed long integer, how do you intend to store it?
long a = +(1 << 62) + 1000;
long b = -(1 << 62);
long dif = a - b; // Overflow, bit truncation
The difference between a and b is wider than 64 bits, so when it's stored into a long integer, its high-order bits are truncated, and you get a strange value for dif.
In other words, you cannot store all possible differences between signed integer values of a given width into a signed integer of the same width. (You can only store half of all of the possible values; the other half require an extra bit.)
Your options are to either use a wider type to hold the difference (which won't help you if you're already using the widest long integer type), or to use a different arithmetic type. If you need at least 64 signed bits of precision, you'll probably need to use BigInteger.
The BigInteger was introduced in .Net 4.0.
There are some open source implementations available in lower versions of the .Net Framework, however you'd be wise to go with the standard.
If the Math.Abs still gives you grief you can implement the function yourself; if the number is negative (a - b < 0) simply trim the negative symbol so its unsigned.
Also, have you tried using Doubles? They hold much larger values.
Here's an alternative that might be interesting to you, but is very much within the confines of a particular int size. This example uses Int32, and uses bitwise operators to accomplish the difference and then the absolute value. This implementation is tolerant of your scenario where a - b equals the min int value, it naturally returns the min int value (not much else you can do, without casting things to the a larger data type). I don't think this is as good an answer as using BigInteger, but it is fun to play with if nothing else:
static int diff(int a, int b)
{
int xorResult = (a ^ b);
int diff = (a & xorResult) - (b & xorResult);
return (diff + (diff >> 31)) ^ (diff >> 31);
}
Here are some cases I ran it through to play with the behavior:
Console.WriteLine(diff(13, 14)); // 1
Console.WriteLine(diff(11, 9)); // 2
Console.WriteLine(diff(5002000, 2346728)); // 2655272
Console.WriteLine(diff(int.MinValue, 0)); // Should be 2147483648, but int data type can't go that large. Actual result will be -2147483648.

Why Do Bytes Carryover?

I have been playing with some byte arrays recently (dealing with grayscale images). A byte can have values 0-255. I was modifying the bytes, and came across a situation where the value I was assigning to the byte was outside the bounds of the byte. It was doing unexpected things to the images I was playing with.
I wrote a test and learned that the byte carries over. Example:
private static int SetByte(int y)
{
return y;
}
.....
byte x = (byte) SetByte(-4);
Console.WriteLine(x);
//output is 252
There is a carryover! This happens when we go the other way around as well.
byte x = (byte) SetByte(259);
Console.WriteLine(x);
//output is 3
I would have expected it to set it to 255 in the first situation and 0 in the second. What is the purpose of this carry over? Is it just due to the fact that I'm casting this integer assignment? When is this useful in the real-world?
byte x = (byte) SetByte(259);
Console.WriteLine(x);
//output is 3
The cast of the result of SetByte is applying modulo 256 to your integer input, effectively dropping bits that are outside the range of a byte.
259 % 256 = 3
Why: The implementers choose to only consider the 8 least significant bits, ignoring the rest.
When compiling C# you can specify whether the assembly should be compiled in checked or unchecked mode (unchecked is default). You are also able to make certain parts of code explicit via the use of the checked or unchecked keywords.
You are currently using unchecked mode which ignores arithmetic overflow and truncates the value. The checked mode will check for possible overflows and throw if they are encountered.
Try the following:
int y = 259;
byte x = checked((byte)y);
And you will see it throws an OverflowException.
The reason why the behaviour in unchecked mode is to truncate rather than clamp is largely for performance reasons, every unchecked cast would require conditional logic to clamp the value when the majority of the time it is unnecessary and can be done manually.
Another reason is that clamping would involve a loss of data which may not be desirable. I don't condone code such as the following but have seen it (see this answer):
int input = 259;
var firstByte = (byte)input;
var secondByte = (byte)(input >> 8);
int reconstructed = (int)firstByte + (secondByte << 8);
Assert.AreEqual(reconstructed, input);
If firstByte came out as anything other than 3 this would not work at all.
One of the places I most commonly rely upon numeric carry over is when implementing GetHashCode(), see this answer to What is the best algorithm for an overridden System.Object.GetHashCode by Jon Skeet. It would be a nightmare to implement GetHashCode decently if overflowing meant we were constrained to Int32.MaxValue.
The method SetByte is irrelevant, simply casting (byte) 259 will also result in 3, since downcasting integral types is implemented as cutting of bytes.
You can create a custom clamp function:
public static byte Clamp(int n) {
if(n <= 0) return 0;
if(n >= 256) return 255;
return (byte) n;
}
Doing arithmetic modulo 2^n makes it possible for overflow errors in different directions to cancel each other out.
byte under = -12; // = 244
byte over = (byte) 260; // = 4
byte total = under + over;
Console.WriteLine(total); // prints 248, as intended
If .NET instead had overflows saturate, then the above program would print the incorrect answer 255.
The bounds control is not active for a case with direct type cast (when using (byte)) to avoid performance reducing.
FYI, result of most operations with operands of byte is integer, excluding the bit operations. Use Convert.ToByte() and you will get an Overflow Exception and you may handle it by assigning the 255 to your target.
Or you may create a fuction to do this check, as mentioned by another guy below.
If the perfomanse is a key, try to add attribute [MethodImpl(MethodImplOptions.AggressiveInlining)]
to that fuction.

How unchecked int overflow work c#

We know that an int value has a maximum value of 2^31 - 1 and a minimum value of -2^31. If we were to set int to the maximum value:
int x = int.MaxValue;
And we take that x and add one to it in a unchecked field
unchecked
{
x++;
}
Then we get x = the minimum value of int. My question is why does this happen and how does it happen in terms of binary.
In C#, the built-in integers are represented by a sequence of bit values of a predefined length. For the basic int datatype that length is 32 bits. Since 32 bits can only represent 4,294,967,296 different possible values (since that is 2^32),
Since int can hold both positive and negative numbers, the sign of the number must be encoded somehow. This is done with first bit. If the first bit is 1, then the number is negative.
Here are the int values laid out on a number-line in hexadecimal and decimal:
Hexadecimal Decimal
----------- -----------
0x80000000 -2147483648
0x80000001 -2147483647
0x80000002 -2147483646
... ...
0xFFFFFFFE -2
0xFFFFFFFF -1
0x00000000 0
0x00000001 1
0x00000002 2
... ...
0x7FFFFFFE 2147483646
0x7FFFFFFF 2147483647
As you can see from this chart, the bits that represent the smallest possible value are what you would get by adding one to the largest possible value, while ignoring the interpretation of the sign bit. When a signed number is added in this way, it is called "integer overflow". Whether or not an integer overflow is allowed or treated as an error is configurable with the checked and unchecked statements in C#.
This representation is called 2's complement
You can check this link if you want to go deeper.
Int has a maximum value of 2^31 - 1 because , int is an alias for Int32 that stores 4 bytes in memory to represent the value.
Now lets come to the concept of int.Max + 1. Here you need to know about the Signed number representations that is used to store the negative values. In Binary number representation, there's nothing like negative numbers but they are represented by the one's complement and two's complement bits.
Lets say, my int1 has a storage memory of 1 byte, ie. 8 bits. So Max value you can store into int1 is 2^8 -1 = 255 . Now let's add 1 into this value-
11111111
+ 00000000
----------
100000000
your output is 100000000 = (512) in decimal, that is beyond the storage capacity of int1 and that represents the negative value of -256 in decimal (as first bit shows the negative value).
This is the reason adding 1 to int.Max become, int.Minimum. ie.
`int.Maximum + 1 = int.Minimum`
Okay, I'm going to assume for sake of convenience that there's a 4 bit integer type in C#. The most significant bit is used to store the sign, the remaining three are used to store the magnitude.
The max number that can be stored in such a representation is +7 (positive 7 in the base 10). In binary, this is:
0111
Now let's add positive one:
0111
+0001
_____
1000
Whoops, that carried over from the magnitudes and flipped the sign bit! The sum you see above is actually the number -8, the smallest possible number that can be stored in this representation. If you're not familiar with two's complement, which is how signed numbers are commonly represented in binary, you might think that number is negative zero (which would be the case in a sign and magnitude representation). You can read up on two's complement to understand this better.

How to know a value overflows without recurring to a runtime OverflowException

So the question is:
Given a native integral type that represents the largest possible number in a given compiler (language?), for example ulong in C#, how do you detect that an input string representing a number is going to overflow the largest value that is representable by that given type without falling back to a checked context and a runtime OveflowException?
Obviously the C# compiler can detect constant integral overflows:
ulong l = 18446744073709551615; //ok
ulong l = 18446744073709551616; //compile time error: Integral constant is too large.
Is the compiler using a runtime OverflowException (or equivalent) under the hood? If so, is there a way to actually do this without recurring to a runtime exception or building a numeric type that can hold larger numbers like System.Numeric.BigInt? It is worth noting that BigInt has no native support in C# as the following is a compile time error although the integral constant is well inside the type's range:
BigInt i = 18446744073709551616; //compile time error: Integral constant is too large.
Would something like this count as a solution?
string s1 = "18446744073709551616";
string s2 = ulong.MaxValue.ToString();
// assuming s1 contains digits only and no leading zeros
if(
s1.Length > s2.Length ||
s1.Length == s2.Length && string.CompareOrdinal(s1, s2) > 0
)
Console.WriteLine("overflow");
The compiler most likely just parses the input one digit at a time, with code similar to that of ulong.Parse but obviously adapted to the task.
The way ulong.Parse decides that it overflows is reasonably simple, but you do need to know how integers are parsed. ulong.Parse parses the input one character at a time. It maintains the ulong result, and for each character, it multiplies the result by 10, then adds the value of the character (which is 0 to 9), and it keeps doing so until the input runs out or the result overflows.
There are two overflow checks, because there are two things that can overflow: the multiplication by 10, and the addition. To check that the multiplication won't overflow, the current result is compared to 1844674407370955161. If the result is greater than that, and there are still digits left, the algorithm exits, reporting overflow. Observe that this number is the same as ulong.MaxValue with the last digit removed, making it the largest integer that can be multiplied by 10 without overflow.
Next, it needs to check whether adding a number from 0 to 9 will overflow. It does so by adding the number first, and then checking whether the result has decreased instead of increasing. This works because of how addition is implemented inside CPUs; basically the top bit of the result is discarded because it can't fit.
And that's it, really. If the characters run out without tripping any of the two checks above, the number is parsed successfully, otherwise it's an overflow.

Categories