Why use a hex literal for an int? - c#

Whilst reading over some existing code I came across:
public static readonly int MaxSize = 0x1000;
Which made me wonder why use a hex literal. In this context MaxSize is used for pagination.
The closest I came to was:
Hex numbers are a convenient way of expressing integral values,
denoting exactly the bits stored in memory for that integer.
https://csharp.2000things.com/2010/08/28/72-hexadecimal-numbers/
Which makes sense to a degree, I'd be interested in hearing a more detailed explanation for this use case in particular "denoting exactly the bits stored in memory".

In some cases HEX value is more rounded and understandable than its decimal equivalent. Like 0x0FFF, 0xA0A0, 0x10000, etc.

Related

Convert.ToDecimal(double x) - System.OverflowException

What is the maximum double value that can be represented\converted to a decimal?
How can this value be derived - example please.
Update
Given a maximum value for a double that can be converted to a decimal, I would expect to be able to round-trip the double to a decimal, and then back again. However, given a figure such as (2^52)-1 as in #Jirka's answer, this does not work. For example:
Test]
public void round_trip_double_to_decimal()
{
double maxDecimalAsDouble = (Math.Pow(2, 52) - 1);
decimal toDecimal = Convert.ToDecimal(maxDecimalAsDouble);
double toDouble = Convert.ToDouble(toDecimal);
//Fails.
Assert.That(toDouble, Is.EqualTo(maxDecimalAsDouble));
}
All integers between -9,007,199,254,740,992 and 9,007,199,254,740,991 can be exactly represented in a double. (Keep reading, though.)
The upper bound is derived as 2^53 - 1. The internal representation of it is something like (0x1.fffffffffffff * 2^52) if you pardon my hexadecimal syntax.
Outside of this range, many integers can be still exactly represented if they are a multiple of a power of two.
The highest integer whatsoever that can be accurately represented would therefore be 9,007,199,254,740,991 * (2 ^ 1023), which is even higher than Decimal.MaxValue but this is a pretty meaningless fact, given that the value does not bother to change, for example, when you subtract 1 in double arithmetic.
Based on the comments and further research, I am adding info on .NET and Mono implementations of C# that relativizes most conclusions you and I might want to make.
Math.Pow does not seem to guarantee any particular accuracy and it seems to deliver a bit or two fewer than what a double can represent. This is not too surprising with a floating point function. The Intel floating point hardware does not have an instruction for exponentiation and I expect that the computation involves logarithm and multiplication instructions, where intermediate results lose some precision. One would use BigInteger.Pow if integral accuracy was desired.
However, even (decimal)(double)9007199254740991M results in a round trip violation. This time it is, however, a known bug, a direct violation of Section 6.2.1 of the C# spec. Interestingly I see the same bug even in Mono 2.8. (The referenced source shows that this conversion bug can hit even with much lower values.)
Double literals are less rounded, but still a little: 9007199254740991D prints out as 9007199254740990D. This is an artifact of internal multiplication by 10 when parsing the string literal (before the upper and lower bound converge to the same double value based on the "first zero after the decimal point"). This again violates the C# spec, this time Section 9.4.4.3.
Unlike C, C# has no hexadecimal floating point literals, so we cannot avoid that multiplication by 10 by any other syntax, except perhaps by going through Decimal or BigInteger, if these only provided accurate conversion operators. I have not tested BigInteger.
The above could almost make you wonder whether C# does not invent its own unique floating point format with reduced precision. No, Section 11.1.6 references 64bit IEC 60559 representation. So the above are indeed bugs.
So, to conclude, you should be able to fit even 9007199254740991M in a double precisely, but it's quite a challenge to get the value in place!
The moral of the story is that the traditional belief that "Arithmetic should be barely more precise than the data and the desired result" is wrong, as this famous article demonstrates (page 36), albeit in the context of a different programming language.
Don't store integers in floating point variables unless you have to.
MSDN Double data type
Decimal vs double
The value of Decimal.MaxValue is positive 79,228,162,514,264,337,593,543,950,335.

Why some types do not have literal modifiers

For example, why long int has a literal modifier, but short int does not? I am referring to the following question on this site: C# compiler number literals
In general, C# seems to be a very well designed and consistent language. Probably there is a strong reason to provide literal modifiers for some types, but not for all. What is it?
Why long int has a literal modifier, but short int does not?
The question is "why does C# not have this feature?" The answer to that question is always the same. Features are unimplemented by default; C# does not have that feature because no one designed, implemented and shipped the feature to customers.
The absence of a feature does not need justification. Rather, all features must be justified by showing that their benefits outweigh their costs. As the person proposing the feature, the onus is on you to describe why you think the feature is valuable; the onus is not on me to explain why it is not.
Probably there is a strong reason to provide literal modifiers for some types, but not for all. What is it?
Now that is a more answerable question. Now the question is "what justifies the literal suffix on long, and why is that not also a justification for a similar literal suffix on short?"
Integers can be used for a variety of purposes. You can use them as arithmetic numbers. You can use them as collections of bit flags. You can use them as indices into arrays. And there are lots of more special-purpose usages. But I think it is fair to say that most of the time, integers are used as arithmetical numbers.
The vast majority of calculations performed in integers by normal programs involve numbers that are far, far smaller than the range of a 32 bit signed integer -- roughly +/- two billion. And lots of modern hardware is extremely efficient when dealing solely with 32 bit integers. It therefore makes sense to make the default representation of numbers to be signed 32 bit integers. C# is therefore designed to make calculations involving 32 bit signed integers look perfectly normal; when you say "x = x + 1" that "1" is understood to be a signed 32 bit integer, and odds are good that x is too, and the result of the sum is too.
What if the calculation is integral but does not fit into the range of a 32 bit integer? "long" 64 bit integers are a sensible next step up; they are also efficient on a lot of hardware and longs have a range that should satisfy the needs of pretty much anyone who isn't doing heavy-duty combinatorics that involve extremely large numbers. It therefore makes sense to have some way to specify clearly and concisely in source code that this literal here is to be treated as a long integer.
Interop scenarios, or scenarios in which integers are used as bit fields, often require the use of unsigned integers. Again, it makes sense to have a way to clearly and concisely specify that this literal is intended to be treated as an unsigned integer.
So, summing up, when you see "1", odds are good that the vast majority of the time the user intends it to be used as a 32 bit signed integer. The next most likely cases are that the user intends it to be a long integer or an unsigned int or unsigned long. Therefore there are concise suffixes for each of those cases.
Thus, the feature is justified.
Why is that not a justification for shorts?
Because first, in every context in which a short is legal, it is already legal to use an integer literal. "short x = 1;" is perfectly legal; the compiler realizes that the integer fits into a short and lets you use it.
Second, arithmetic is never done in shorts in C#. Arithmetic can be done in ints, uints, longs and ulongs, but arithmetic is never done in shorts. Shorts promote to int and the arithmetic is done in ints, because like I said before, the vast majority of arithmetic calculations fit into an int. The vast majority do not fit into a short. Short arithmetic is possibly slower on modern hardware which is optimized for ints, and short arithmetic does not take up any less space; it's going to be done in ints or longs on the chip.
You want a "long" suffix to tell the compiler "this arithmetic needs to be done in longs" but a "short" suffix doesn't tell the compiler "this arithmetic needs to be done in shorts" because that's simply not a feature of the C# language to begin with.
The reasons for providing a long suffix and an unsigned syntax do not apply to shorts. If you think there is a compelling benefit to the feature, state what the benefit is. Without a benefit to justify its costs, the feature will not be implemented in C#.
According to MSDN:
short x = 32767;
In the preceding declaration, the integer literal 32767 is implicitly
converted from int to short. If the integer literal does not fit into
a short storage location, a compilation error will occur.
So it is a compile time feature. short does not have a suffix because it would never be needed.
The related question probably is : Why do long, float and decimal do have suffixes?
And a short answer would be that i + 1 and i + 1L can produce different values and are therefore of different types.
But there exists no such thing as 'short arithmetic', short values are always converted to int when used in a calculation.
As Eric points out in the comment, my answer below doesn't make sense. I think it's more correct to say that the inability to express a short literal in C# and the inability to express a short literal in IL share a common cause (the lack of a compelling reason for the feature.) VB.Net apparently has a short literal specifier, which is interesting (for backwards compatibility with VB syntax?) In any case, I've left the answer here as some of the information may be interesting, even if the reasoning is incorrect.
There is no short literal because there is not actually any way for a short literal to be loaded in IL, the underlying language used by the CLR. This is because all 'short' types (anything smaller than an int) are implicitly widened to an int when loaded onto the operation stack. Signed and unsigned are likewise a matter of operations and not actually 'stored' with the active number on the operation stack. The 'short' types only come into play when you want to store a number on the operation stack into a memory location, so there are IL operations to Convert to various 'short' types (though it actually still widens the number back to an int after the conversion; it just makes sure that the value will be suitable for storing into a field of the 'short' type.)
Long types have a literal specifier, on the other hand, due to the fact that they are treated differently on the operation stack. There is a separate Ldc_I8 instruction for loading constant long values. There are also Ldc_R4 (hence why you need 'f' for float) and Ldc_R8 (C# chooses this as it's default if you use a decimal number without a specifier.) Decimal is a special case, as it's not actually a primitive type in IL; it just has a built-in constant specifier 'm' in C# that compiles to a constructor call.
As for why there are no special short operations (and corresponding short literals), that's likely because most current CPU architectures do not operate with registers smaller than 32-bits, so there is no distinction at the CPU level worth exploiting. You could potentially save code size (in terms of bytes of IL) by allowing for 'short' load IL opcodes, but at the cost of additional complexity for the jitter; the code space saved is probably not worth it.
Since a short can be implicitly converted to int, long, float, double, or decimal; there's no need for a literal modifier.
Consider:
void method(int a) {}
void method2()
{
short a = 4;
method(a); // no problems
}
You may notice that char and byte are also with literal modifiers, for possibly this same reason.
From To
sbyte short, int, long, float, double, or decimal
byte short, ushort, int, uint, long, ulong, float, double, or decimal
short int, long, float, double, or decimal
ushort int, uint, long, ulong, float, double, or decimal
int long, float, double, or decimal
uint long, ulong, float, double, or decimal
long float, double, or decimal
char ushort, int, uint, long, ulong, float, double, or decimal
float double
ulong float, double, or decimal
If you declare a literal short and make it larger than Short.MaxValue a compiler error will occur, otherwise the literal will be a short.
The time I have "worked in Short" was for values that are stored in a Database.
They are positive integer values that will rarely go over 10 to 20.(a byte or sbyte would be big enough, but I figured a little over kill would keep me from regretting my choice, if the code got reused in a slightly different way)
The field is used to let the user sort the records in a table. This table feeds a drop down or radio button list that is ordered by "time" (step one, step two, ...).
Being new to C# (and old enough to remember when counting bytes was important) I figured it would be a little more efficient. I don't do math on the values. I just Sort them (and swap them between records). The only math so far has been "MaxInUse"+1 (for new records), which is a special case "++MaxInUse". This is good, because the lack of a literal means "s = s+2" would have to be "s = (Int16)(s+2)".
Now that I see how annoying C# makes working with the other ints, I expect to join the modern world and waste bytes, JUST to make the compiler happy.
But, shouldn't "making the compiler happy" rank about #65 in our top 10 programming goals?
Is it EVER an advantage to have the compiler complain about adding the integer "2" to ANY of the INTEGER types? It should complain about "s=123456", but that's a different case.
If anyone does have to deal with math AND shorts, I suggest you make your own literals. (How many could you need?)
short s1= 1, s2 = 2, s123 = 123;
Then s = s + s2 is only a little annoying (and confusing for those who follow after you).

Happy 3501.ToString("X") day!

In C#, is there a way to convert an int value to a hex value without using the .ToString("X") method?
Your question is plain wrong (no offense intended). A number has one single value. Hex, Decimal, Binary, Octal, etc. are just different representations of one same integral number. Int32 is agnostic when it comes to what representation you choose to write it with.
So when you ask:
is there a way to convert an int value to a hex value
you are asking something thast doesn't make sense. A valid question would be: is there anyway to write a integer in hexadecimal representation that doesn't involve using .ToString("X")?
The answer is not really. Someway or the other (directly or not by you), .ToString("X") or some other flavor of ToString() will be called to correctly format the string representing the value.
And when you think of hexadecimal as a respresentation (a formatted string) of a given number, then .ToString() does make sense.
Use Convert.ToString( intValue, 16 );
It can be used to convert between any common numeric base, i.e., binary, octal, decimal and hexadecimal.

How do you deal with numbers larger than UInt64 (C#)

In C#, how can one store and calculate with numbers that significantly exceed UInt64's max value (18,446,744,073,709,551,615)?
Can you use the .NET 4.0 beta? If so, you can use BigInteger.
Otherwise, if you're sticking within 28 digits, you can use decimal - but be aware that obviously that's going to perform decimal arithmetic, so you may need to round at various places to compensate.
By using a BigInteger class; there's one in the the J# libraries (definitely accessible from C#), another in F# (need to test this one), and there are freestanding implementations such as this one in pure C#.
What is it that you wish to use these numbers for? If you are doing calculations with really big numbers, do you still need the accuracy down to the last digit?
If not, you should consider using floating point values instead. They can be huge, the max value for the double type is 1.79769313486231570E+308, (in case you are not used to scientific notation it means 1.79769313486231570 multiplied by 10000000...0000 - 308 zeros).
That should be large enough for most applications
BigInteger represents an arbitrarily large signed integer.
using System.Numerics;
var a = BigInteger.Parse("91389681247993671255432112000000");
var b = new BigInteger(1790322312);
var c = a * b;
Decimal has greater range.
There is support for bigInteger in .NET 4.0 but that is still not out of beta.
There are several libraries for computing with big integers, most of the cryptography libraries also offer a class for that. See this for a free library.
Also, do check that you truly need a variable with greater capacity than Int64 and aren't falling foul of C#'s integer arithmetic.
For example, this code will yield an overflow error:
Int64 myAnswer = 20000*1024*1024;
At first glance that might seem to be because the result is too large for an Int64 variable, but actually it's because each of the numbers on the right side of the formula are implicitly typed as Int32 so the temporary memory space reserved for the result of the calculation will be Int32 size, and that's what causes the overflow.
The result will actually easily fit into an Int64, it just needs one of the values on the right to be cast to Int64:
Int64 myAnswer = (Int64)20000*1024*1024;
This is discussed in more detail in this answer.
(I appreciate this doesn't apply in the OP's case, but it was just this sort of issue that brought me here!)
You can use decimal. It is greater than Int64.
It has 28-29 significant digits.

enum with value 0x0001?

I have an enum declaration like this:
public enum Filter
{
a = 0x0001;
b = 0x0002;
}
What does that mean? They are using this to filter an array.
It means they're the integer values assigned to those names. Enums are basically just named numbers. You can cast between the underlying type of an enum and the enum value.
For example:
public enum Colour
{
Red = 1,
Blue = 2,
Green = 3
}
Colour green = (Colour) 3;
int three = (int) Colour.Green;
By default an enum's underlying type is int, but you can use any of byte, sbyte, short, ushort, int, uint, long or ulong:
public enum BigEnum : long
{
BigValue = 0x5000000000 // Couldn't fit this in an int
}
It just means that if you do Filter->a, you get 1. Filter->b is 2.
The weird hex notation is just that, notation.
EDIT:
Since this is a 'filter' the hex notation makes a little more sense.
By writing 0x1, you specify the following bit pattern:
0000 0001
And 0x2 is:
0000 0010
This makes it clearer on how to use a filter.
So for example, if you wanted to filter out data that has the lower 2 bits set, you could do:
Filter->a | Filter->b
which would correspond to:
0000 0011
The hex notation makes the concept of a filter clearer (for some people). For example, it's relatively easy to figure out the binary of 0x83F0 by looking at it, but much more difficult for 33776 (the same number in base 10).
It's not clear what it is that you find unclear, so let's discuss it all:
The enum values have been given explicit numerical values. Each enum value is always represented as a numerical value for the underlying storage, but if you want to be sure what that numerical value is you have to specify it.
The numbers are written in hexadecimal notation, this is often used when you want the numerical values to contain a single set bit for masking. It's easier to see that the value has only one bit set when it's written as 0x8000 than when it's written as 32768.
In your example it's not as obvious as you have only two values, but for bit filtering each value represents a single bit so that each value is twice as large as the previous:
public enum Filter {
First = 0x0001,
Second = 0x0002,
Third = 0x0004,
Fourth = 0x0008
}
You can use such an enum to filter out single bits in a value:
If ((num & Filter.First) != 0 && (num & Filter.Third) != 0) {
Console.WriteLine("First and third bits are set.");
}
It could mean anything. We need to see more code then that to be able to understand what it's doing.
0x001 is the number 1. Anytime you see the 0x it means the programmer has entered the number in hexadecimal.
Those are literal hexadecimal numbers.
Main reason is :
It is easyer to read hex notation when writing numbers such as : "2 to the power of x" is needed.
To use enum type as bit flag, we need to increment enum values by power of 2 ...
1,2,4,8,16,32,64, etc. To keep it readable, hex notation is used.
Ex : 2^10 is 0x10000 in hex (neat and clean), but it is written 65536 in classical decimal notation ... Same for 0x200 (hex notation) and 512. (2^9)
Those look like they are bit masks of some sort. But their actual values are 1 and 2...
You can assign values to enums such as:
enum Example {
a = 10,
b = 23,
c = 0x00FF
}
etc...
Using Hexidecimal notation like that usually indicates that there may be some bit manipulation. I've used this notation often when dealing with this very thing, for the very reason you asked this question - this notation sort of pops out at you and says "Pay attention to me I'm important!"
Well we can use integers infact we can avoid any as the default nature of enum assigns 0 to its first member and an incremented value to the next available member. Many developers use this to hit two targets with one bow.
Complicate the code making it difficult to understand
Faster the performance as hex codes are nearer to binary one
my view is if we are still using why we are in fourth generation language just move to binary again
but its quite better technique to play with bits and encryption/decryption process

Categories