Why doesn't this overflow? - c#

Given this code:
int x = 20000;
int y = 20000;
int z = 40000;
// Why is it printing WTF? Isn't 40,000 > 32,767?
if ((x + y) == z) Console.WriteLine("WTF?");
And knowing an int can hold −32,768 to +32,767. Why doesn't this cause an overflow?

In C#, the int type is mapped to the Int32 type, which is always 32-bits, signed.
Even if you use short, it still won't overflow because short + short returns an int by default. If you cast this int to short - (short)(x + y) - you'll get an overflowed value. You won't get an exception though. You can use checked behavior to get an exception:
using System;
namespace TestOverflow
{
class Program
{
static void Main(string[] args)
{
short x = 20000;
short y = 20000;
short z;
Console.WriteLine("Overflowing with default behavior...");
z = (short)(x + y);
Console.WriteLine("Okay! Value is {0}. Press any key to overflow " +
"with 'checked' keyword.", z);
Console.ReadKey(true);
z = checked((short)(x + y));
}
}
}
You can find information about checked (and unchecked) on MSDN. It basically boils down to performance, because checking for overflow is a little bit slower than ignoring it (and that's why the default behavior is usually unchecked, but I bet that in some compilers/configurations you'll get an exception on the first z assignment.)

http://msdn.microsoft.com/en-us/library/5kzh1b5w.aspx
Type: int
Range: -2,147,483,648 to 2,147,483,647

While everyone is correct in saying that an "int" type on a 32 bit machine is most likely 2^32, there is a glaring flaw in your methodology.
Let's assume that int was 16 bit. You're assigning a value that will overflow z, so z itself is overflowed. When you calculate x+y you're also overflowing the int type, it's very likely that both cases will overflow to the same value, meaning you'd hit your equality regardless(this is probably compiler dependent, I'm not quite sure whether x+y will be promoted).
The correct way to do your experiment would be for z to have a larger data type than x and y. For example(Sorry for plain C, I'm not much of C# person. Hopefully it illustrated the methodology, however.)
int x = INT_MAX;
int y = INT_MAX;
int sum = x + y;
long long z = INT_MAX+INT_MAX;
if(sum == z)
printf("Why didn't sum overflow?!\n");
Comparing sum and z is important as comparing x+y and z may still come out fine depending on how the compiler handles promotion.

In C#, an Int is 4 bytes. So it maxes out at 2^31 or 2,147,483,648. If you want a 2 byte integer, use a short instead of an int.

Because an int in .NET is a signed 32 bit number with a range of -2,147,483,648 to 2,147,483,647.
Reference : http://msdn.microsoft.com/en-us/library/5kzh1b5w(VS.80).aspx

Because ints are 32-bit, holding values up to ±2GB.

An int's size is 4 byte so it can hold at least 2^31 which is around 2 billion.

The int keyword maps to the .NET Framework Int32 type, which can hold integers in the range from -2,147,483,648 to 2,147,483,647.

in C# int (System.Int32) is of 32 bits which can happily store this value.

you are given to print the result as "WTF?" .Then how should it display other value.
Int means int32 its range is –2147483648 to 2147483647
you are given the range of int16 :–32768 to 32767
This is the reason it is not throwing any error

First of all your code is in the range for int... However if it were not in the range then it wont complain either... coz you are never assigning a value back to any variable after doing X+Y in your if check...
Suppose if you were doing X * Y then it'll be calculated and the result would be a long value then the value from variable Z is taken and promoted to a long then both would be compared... Remember the casting from a lower range primitive to upper range primitive value is implicit.
int x = 200000; //In your code it was 20000
int y = 200000; //In your code it was 20000
int z = 40000;
// Why is it printing WTF? Isn't 40,000 > 32,767?
// Note: X + Y = 200000 and not < 32,767
// would pass compiler coz you are not assigning and values are compared as longs
// And since it's not equals to 40,000 the WTF did not got printed
if ((x + y) == z) Console.WriteLine("WTF?");
// And x * y >= z is true WTF MULTIPLY got printed
if ((x * y) >= z) Console.WriteLine("WTF MULTIPLY?");
// Compiler would fail since x can't hold 40,00,00,00,000
x = x * y;

All the above is true, however, it's important to know, that if you assign a number greater than 2^32, it will not compile!

Related

Does double z=x-y guarantee that z+y==x for IEEE 754 floating point?

I have a problem that can be reduced to this problem statement:
Given a series of doubles where each is in the range [0, 1e7],
modify the last element such that the sum of the numbers equals
exactly a target number. The series of doubles already sums to the
target number within an epsilon (1e-7), but they are not ==.
The following code is working, but is it guaranteed to work for all inputs that meet the requirements described in the first sentence?
public static double[] FixIt(double[] input, double targetDouble)
{
var result = new double[input.Length];
if (input.Length == 0) return result;
double sum = 0;
for (int i = 0; i < input.Length - 1; i++)
{
sum += input[i];
result[i] = input[i];
}
double remainder = targetDouble - sum;
result[result.Length - 1] = remainder;
return result;
}
var arr1 = Enumerable.Repeat(Math.PI / 13, 13).ToArray();
var arr2 = FixIt(arr1, Math.PI);
Debug.Print(Math.PI.ToString("R")); //3.1415926535897931
Debug.Print(arr1.Sum().ToString("R")); //3.1415926535897922
Debug.Print(arr2.Sum().ToString("R")); //3.1415926535897931
A previous version of this question asked about modifying the first element, but modifying the last element simplifies the problem to a known sum and a known target, leaving us with just the question of whether last = target-sum implies that sum+last == target.
(Without NaN of course, and the restrictions on ranges imply some restrictions on last as well that might help.)
Regarding the real problem: We've had this problem surface a number of times in a variety of ways, but what we are trying to do at the moment is reduce the floating point error that crops up due to numerical instabilities in a linear programming solver (Coin-OR CBC). For example, there are 6 variables which all must be in the range [0,X] and the sum of the variables must also be X. Due to numerical instability, the solver occasionally returns slightly negative values and values that do not sum to exactly X. We've overcome the negative number issues - now just trying to resolve the sum to X issue. (Yes, there may be constraints that are being disobeyed by us changing the results, but making sure these numbers sum to X is of higher priority, where the other constraints are not as important.)
z = x-y; does not guarantee z+y == x, and there is not always a solution for the problem of finding a z such z+y == x. A proof follows.
We assume IEEE-754 binary floating-point arithmetic with rounding to nearest, ties to even. The basic 64-bit format is used, but the result holds for other formats. Note that the 64-bit format uses 53-bit significands, meaning that only numbers with 53 or fewer significant binary digits can be represented.
Consider a target x equal to 1+2−52. Let y be 2−53. Then, after z = x-y;, z+y == x evaluates to false. The arithmetic details are shown below, but:
z = x-y; sets z to 1, and then z+y produces 1, which is less than x.
If we increase z to the next representable number, 1+2−52, then z+y produces 1+2−51, which is greater than x.
So there is no value of z that makes z+y == x true.
Details:
The mathematical result of x−y is 1+2−53. As this has 54 significant bits (from 20 to 2−53), it is not representable, and the computed result of x-y must be rounded. The two nearest numbers are 1 and 1+2−52. The ties-to-even rule produces the former number, 1, as the low bit of its significand is 0, while the low bit for 1+2−52 is 1.
Thus z = x-y; sets z to 1.
Then the mathematical result of z+y is 1+2−53. As above, this is rounded to 1, so the computed result of z+y is 1. So z+y == x compares 1 to 1+2−52 and produces false.
Furthermore, no value of z could make the comparison true. If we increment z by the smallest available step, from 1 to 1+2−52, the mathematical sum of z+y is then 1+2−52+2−53. This is midway between the two representable numbers 1+2−52 and 1+2−51. The former has a low bit of 1, and the latter has a low bit of 0, so the computed result of this z+y is 1+2−51, which is of course not equal to 1+2−52.
Floating-point addition is weakly monotonic, so there are no values of z that would produce 1+2−52 for z+y.
No, it doesn't. Here's a concrete counter-example; coded in Python, but you can easily repeat the same experiment in C#:
>>> x = 0.24999916553497312
>>> y = 1.0000153779983518
>>> z = -0.7500162124633787
>>> z == x - y
True
>>> z + y == x
False
Here's a small counter-example with x, y, z all positive:
>>> x = 0.4500000000000001
>>> y = 0.20000000000000004
>>> z = 0.2500000000000001
>>> z == x - y
True
>>> z + y == x
False
Floating point arithmetic is not exact, by definition (unless you're only dealing with integers (edit for correctness: up to 253 i.e. 9007199254740992)); you will always have rounding discrepancies. If you want the rounding to match what humans expect: use decimal instead of double. If you do the same thing with decimal, it will work correctly for any set of numbers that aren't pathological in terms of the decimal digits.

C# Comparer.Default<short>.Compare and Comparer.Default<byte> doesn't return -1, 0 or 1

What's the reason behind all "numeric" comparers (such as Comparer.Default<int>, Comparer.Default<long>, etc.) returning either -1, 0 or 1, but Comparer.Default<short> and Comparer.Default<byte> will return the difference between the two compared numbers?
Is it an optimization feature (returning the difference being faster) and/or because the possible difference between two shorts or two bytes will fit into an int (the Comparer<T>.Compare return type)? But the difference between two ints will not (Comparer<T>.Compare(int.MinValue, int.MaxValue) for example)
Based on the comments in the code it is the latter:
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
For example, say we had the same implementation as short or byte for int:
private int Compare(int x, int y)
{
return x - y;
}
Now, the IComparer contract states that if the result of Compare is:
Less than zero, then x < y;
Greater than zero, then x > y;
Zero, then x == y;
But, given the implementation above, if we pass a sufficiently large negative integer as the first argument, the subtraction will overflow and wrap to a really large positive number:
Compare(Int32.MinValue, 1); // returns 2147483647
That is the result would incorrectly indicate that Int32.MinValue is greater than 1.
Given that IComparer is defined as:
public int Compare (T x, T y);
That is, the result type is an int, it is safe to just perform the subtraction of the arguments short or byte as it will never cause the int result to overflow.
I think you got it exactly right. An int difference does not fit into an int but a byte difference always does.
The return value of Compare is specified to only matter regarding the sign. Therefore, it is a valid and useful performance optimization to return the difference of x and y for smaller types.
In case you are interested: Other languages do not necessarily follow the sign model (< 0, 0, > 0) at all. Some, such as Haskell, return an enum that has the three possible values Less, Equal, Greater. This is cleaner but slower.

Get the sign of a number in C# without conditional statement

Just out of curiosity, is there a way to get the sign of a number, any kind (but obviously a signed type), not just integer using some bitwise/masking, or other kind of, operation?
That is without using any conditional statement or calling the Math.Sign() function.
Thanks in advance!
EDIT: I recognize it was a misleading question. What I had in mind more likely something like: "get the same output of the Math.Sign() or, simplifying get 0 if x <= 0, 1 otherwise".
EDIT #2: to all those asking for code, I didn't have any in mind when I posted the question, but here's an example I came up with, just to give a context of a possible application:
x = (x < 0) ? 0 : x;
Having the sign into a variable could lead to:
x = sign * x; //where sign = 0 for x <= 0, otherwise sign = 1;
The aim would be to achieve the same result as the above :)
EDIT #3: FOUND IT! :D
// THIS IS NOT MEANT TO BE PLAIN C#!
// Returns 0 if x <= 0, 1 otherwise.
int SignOf(x)
{
return (1+x-(x+1)%x)/x;
}
Thanks to everyone!
is there a way to get the sign of a number (any kind, not just integer)
Not for any number type, no. For an integer, you can test the most significant bit: if it's 1, the number is negative. You could theoretically do the same with a floating point number, but bitwise operators don't work on float or double.
Here's a "zero safe" solution that works for all value types (int, float, double, decimal...etc):
(value.GetHashCode() >> 31) + 1;
Output: 1 = 1, -1 = 0, 0.5 = 1, -0.5 = 0, 0 = 1
It's also roughly 10% cheaper than (1+x-(x+1)%x)/x; in C#. Additionally if "value" is an integer, you can drop the GetHashCode() function call in which case (1+x-(x+1)%x)/x; is 127% more expensive ((value >> 31) + 1; is 56% cheaper).
Since 0 is positive it is illogical for a result of 1 for positive numbers & a result of 0 for 0. If you could parametrise -0 you would get an output of 0.
I understand that GetHashCode() is a function call, but the inner workings of the function in the C# language implementation is entirely "arithmetic". Basically the GetHashCode() function reads the memory section, that stores your float type, as an integer type:
*((int*)&singleValue);
How the GetHashCode function works (best source I could find quickly) - https://social.msdn.microsoft.com/Forums/vstudio/en-US/3c3fde60-1b4a-449f-afdc-fe5bba8fece3/hash-code-of-floats?forum=netfxbcl
If you want the output value to be 1 with the same sign as the input, use:
((float.GetHashCode() >> 31) * 2) + 1;
The above floating-point method is roughly 39% cheaper than System.Math.Sign(float) (System.Math.Sign(float) is roughly 65% more expensive). Where System.Math.Sign(float) throws an exception for float.NaN, ((float.NaN.GetHashCode() >> 31) * 2) + 1; does not and will return -1 instead of crashing.
or for integers:
((int >> 31) * 2) + 1;
The above integer method is roughly 56% cheaper than System.Math.Sign(int) (System.Math.Sign(int) is roughly 125% more expensive).
It depends on the type of number value type you are targeting.
For signed Integers C# and most computer systems use the so called Ones' complement representation.
That means the sign is stored in the first bit of the value.
So you can extract the sign like this:
Int16 number = -2;
Int16 sign = (number & Int16.MinValue) >> 16;
Boolean isNegative = Convert.ToBoolean(sign);
Note that up until now we have not used any conditional operator (explicitly anyways)
But: You still don't know whether the number has a sign or not.
The logical equivalent of your question: "How do I know, if my number is negative?" explicitly requires the usage of a conditional operator as the question is, after all conditional.
So you won't be able to dodge:
if(isNegative)
doThis();
else
doThat();
to just get the sign, you can avoid conditional operators as you will see below in Sign extension of int32 struct. however to get the name I dont think you can avoid conditional operator
class Program
{
static void Main(string[] args)
{
Console.WriteLine(0.Sign());
Console.WriteLine(0.SignName());
Console.WriteLine(12.Sign());
Console.WriteLine(12.SignName());
Console.WriteLine((-15).Sign());
Console.WriteLine((-15).SignName());
Console.ReadLine();
}
}
public static class extensions
{
public static string Sign(this int signedNumber)
{
return (signedNumber.ToString("+00;-00").Substring(0, 1));
}
public static string SignName(this int signedNumber)
{
return (signedNumber.ToString("+00;-00").Substring(0, 1)=="+"?"positive":"negative");
}
}
if x==0 you will have a divby0 exception with this code you posted:
int SignOf(x) {
return (1+x-(x+1)%x)/x; }

C# Bitwise Operator With Ints

What does this expression actually mean??
Note - the x and y vars are just sample values.
int x = 3;
int y = 1;
if ((x & y) !=0)
I inherited a codebase and am not up to speed on bitwise operators. I have read up, but am still missing something. Help!
It's comparing the bits in each value. It returns any bits that are set in both numbers.
In your example:
3: 0011
1: 0001
3 & 1: 0001
This checks whether x and y both have at least one common bit set. In the case of your example this would be the true.
if ((x & y) != 0)
This would typically be used to determine whether the value x has a specific bit-flag (y) set. The AND operator returns an integer with only those bits set that are set in both operands.

Math Round to always upper integer

I need to find a division of two integers and round it to next upper integer
e.g x=7/y=5 = 2; here x and y always greater than 0
This is my current code
int roundValue = x % y > 0? x / y + 1: x / y;
Is there any better way to do this?
You could use Math.Ceiling... but that will require converting to/from double values.
Another alternative is to use Math.DivRem to do both parts at the same time.
public static int DivideRoundingUp(int x, int y)
{
// TODO: Define behaviour for negative numbers
int remainder;
int quotient = Math.DivRem(x, y, out remainder);
return remainder == 0 ? quotient : quotient + 1;
}
Try (int)Math.Ceiling(((double)x) / y)
All solutions looks too hard. For upper value of x/y, use this one
( x + y - 1 ) / y
dunno what's better way or how to define a better way (if in terms of performance you have to run tests to see which will be faster), but here's my solution:
int roundValue = x / y + Convert.ToInt32(x%y>0);
p.s.
still have to deal somehow with neg. numbers... IMO this is the simplest.
+0.5 will aways round to the higher.
Use ceil() function.
It gives the upper value.
It's better to use MidpointRounding from Math.Round
In your case:
Math.Round(value, MidpointRounding.AwayFromZero);
see more: https://learn.microsoft.com/ru-ru/dotnet/api/system.math.round?view=net-6.0#system-math-round(system-double-system-midpointrounding)

Categories

Resources