How you can represent binary numbers on label? - c#

I converted decimal to binary number however i dont know how to represent on label. I have a list of numbers 0 and 1,Now, how do I display the information on labels.In fact, i dont know how to represent on label.
private void btnRun_Click(object sender, EventArgs e)
{
var decimaltoBinary = fnDecimalToBinary(Convert.ToInt32(txtenterNumber.Text));
}
private List<int> fnDecimalToBinary(int number)
{
int[] decimalNumbers = new int[] { 1, 2, 4, 8, 16, 32, 64, 128, 256 };
List<int> binaryNumbers = new List<int>();
int locDecimalArray = 0;
int sumNumber = 0;
for (int i = 0; i < decimalNumbers.Length; i++)
{
if (number < decimalNumbers[i])
{
sumNumber = number;
locDecimalArray = i - 1;
for (int j = locDecimalArray; j >= 0; j--)
{
if (sumNumber == 0)
{
binaryNumbers.Add(0);
return binaryNumbers;
}
else if (sumNumber >= decimalNumbers[j])
{
sumNumber = sumNumber - decimalNumbers[j];
binaryNumbers.Add(1);
}
else if (sumNumber < decimalNumbers[j])
{
binaryNumbers.Add(0);
}
}
return binaryNumbers;
}
}
return binaryNumbers;
}

It seems that you've received a comment that explains how you can convert your List<int> to the string value you need for the Label control. However, it seems to me that for the purposes of this exercise, you might benefit from some help with the decimal-to-binary conversion itself. There are already a number of similar questions on Stack Overflow dealing with this scenario (as you can guess, converting to binary text is a fairly common programming exercise), but of course none will start with your specific code, so I think it's worth writing yet another answer. :)
Basing the conversion on a pre-computed list of numeric values is not a terrible way to go, especially for the purposes of learning. But your version has a bunch of extra code that's just not necessary:
Your outer loop doesn't accomplish anything except verify that the number passed is within the range permitted by your pre-computed values. But this can be done as part of the conversion itself.
Furthermore, I'm not convinced that returning an empty list is really the best way to deal with invalid input. Throwing an exception would be more appropriate, as this forces the caller to deal with errors, and allows you to provide a textual message for display to the user.
The value 0 is always less than any of the digit values you've pre-computed, so there's no need to check for that explicitly. You really only need the if and a single else inside the inner loop.
Since you are the one populating the array, and since for loops are generally more readable when they start at 0 and increment the index as opposed to starting at the end and decrement, it seems to me that you would be better off writing the pre-computed values in reverse.
Entering numbers by hand is a pain and it seems to me that the method could be more flexible (i.e. support larger binary numbers) if you allowed the caller to pass the number of digits to produce, and used that to compute the values at run-time (though, if for performance reasons that's less desirable, pre-computing the largest digits that would be used and storing that in a static field, and then just using whatever subset of that you need, would be yet another suitable approach).
With those changes, you would get something like this:
private List<int> DecimalToBinary(int number, int digitCount)
{
// The number can't itself have more than 32 digits, so there's
// no point in allowing the caller to ask for more than that.
if (digitCount < 1 || digitCount > 32)
{
throw new ArgumentOutOfRangeException("digitCount",
"digitCount must be between 1 and 32, inclusive");
}
long[] digitValues = Enumerable.Range(0, digitCount)
.Select(i => (long)Math.Pow(2, digitCount - i - 1)).ToArray();
List<int> binaryDigits = new List<int>(digitCount);
for (int i = 0; i < digitValues.Length; i++)
{
if (digitValues[i] <= number)
{
binaryDigits.Add(1);
number = (int)(number - digitValues[i]);
}
else
{
binaryDigits.Add(0);
}
}
if (number > 0)
{
throw new ArgumentOutOfRangeException("digitCount",
"digitCount was not large number to accommodate the number");
}
return binaryDigits;
}
And here's an example of how you might use it:
private void button1_Click(object sender, EventArgs e)
{
int number;
if (!int.TryParse(textBox1.Text, out number))
{
MessageBox.Show("Could not convert user input to an int value");
return;
}
try
{
List<int> binaryDigits = DecimalToBinary(number, 8);
label3.Text = string.Join("", binaryDigits);
}
catch (ArgumentOutOfRangeException e1)
{
MessageBox.Show("Exception: " + e1.Message, "Could not convert to binary");
}
}
Now, the above example fits the design you originally had, just cleaned it up a bit. But the fact is, the computer already knows binary. That's how it stores numbers, and even if it didn't, C# includes operators that treat the numbers as binary (so if the computer didn't use binary, the run-time would be required to translate for you anyway). Given that, it's actually a lot easier to convert just by looking at the individual bits. For example:
private List<int> DecimalToBinary2(int number, int digitCount)
{
if (digitCount < 1 || digitCount > 32)
{
throw new ArgumentOutOfRangeException("digitCount",
"digitCount must be between 1 and 32, inclusive");
}
if (number > Math.Pow(2, digitCount) - 1)
{
throw new ArgumentOutOfRangeException("digitCount",
"digitCount was not large number to accommodate the number");
}
List<int> binaryDigits = new List<int>(digitCount);
for (int i = digitCount - 1; i >= 0; i--)
{
binaryDigits.Add((number & (1 << i)) != 0 ? 1 : 0);
}
return binaryDigits;
}
The above simply starts at the highest possible binary digit (given the desired count of digits), and checks each individual digit in the provided number, using the "bit-shift" operator << and the logical bitwise "and" operator &. If you're not already familiar with binary arithmetic, shift operations, and these operators, this might seem like overkill. But it's actually a fundamental aspect of how computers work, worth knowing, and of course as shown above, can dramatically simplify code required to deal with binary data (to the point where parameter validation code takes up half the method :) ).
One last thing: this entire discussion ignores the fact that you're using a signed int value, rather than the unsigned uint type. Technically, this means your code really ought to be able to handle negative numbers as well. However, doing so is a bit trickier when you also want to deal with binary digit counts that are less than the natural width of the number in the numeric type (e.g. 32 bits for an int). Conversely, if you don't want to support negative numbers, you should really be using the uint type instead of int.
I figured that trying to address that particular complication would dramatically increase the complexity of this answer and take away from the more fundamental details that seemed worth conveying. So I've left that out. But I do encourage you to look more deeply into how computers represent numbers, and why negative numbers require more careful handling than the above code is doing.

Related

Reducing a BigInteger value in C#

I'm somewhat new to working with BigIntegers and have tried some stuff to get this system working, but feel a little stuck at the moment and would really appreciate a nudge in the right direction or a solution.
I'm currently working on a system which reduces BigInteger values down to a more readable form, and this is working fine with my current implementation, but I would like to further expand on it to get decimals implemented.
To better give a picture of what I'm attempting, I'll break it down.
In this context, we have a method which is taking a BigInteger, and returning it as a string:
public static string ShortenBigInt (BigInteger moneyValue)
With this in mind, when a number such as 10,000 is passed to this method, 10k will be returned. Same for 1,000,000 which will return 1M.
This is done by doing:
for(int i = 0; i < prefixes.Length; i++)
{
if(!(moneyValue >= BigInteger.Pow(10, 3*i)))
{
moneyValue = moneyValue / BigInteger.Pow(10, 3*(i-1));
return moneyValue + prefixes[i-1];
}
}
This system is working by grabbing a string from an array of prefixes and reducing numbers down to their simplest forms and combining the two and returning it when inside that prefix range.
So with that context, the question I have is:
How might I go about returning this in the same way, where passing 100,000 would return 100k, but also doing something like 1,111,111 would return 1.11M?
Currently, passing 1,111,111M returns 1M, but I would like that additional .11 tagged on. No more than 2 decimals.
My original thought was to convert the big integer into a string, then chunk out the first few characters into a new string and parse a decimal in there, but since prefixes don't change until values reach their 1000th mark, it's harder to tell when to place the decimal place.
My next thought was using BigInteger.Log to reduce the value down into a decimal friendly number and do a simple division to get the value in its decimal form, but doing this didn't seem to work with my implementation.
This system should work for the following prefixes, dynamically:
k, M, B, T, qd, Qn, sx, Sp,
O, N, de, Ud, DD, tdD, qdD, QnD,
sxD, SpD, OcD, NvD, Vgn, UVg, DVg,
TVg, qtV, QnV, SeV, SPG, OVG, NVG,
TGN, UTG, DTG, tsTG, qtTG, QnTG, ssTG,
SpTG, OcTG, NoTG, QdDR, uQDR, dQDR, tQDR,
qdQDR, QnQDR, sxQDR, SpQDR, OQDDr, NQDDr,
qQGNT, uQGNT, dQGNT, tQGNT, qdQGNT, QnQGNT,
sxQGNT, SpQGNT, OQQGNT, NQQGNT, SXGNTL
Would anyone happen to know how to do something like this? Any language is fine, C# is preferable, but I'm all good with translating. Thank you in advance!
formatting it manually could work a bit like this:
(prefixes as a string which is an char[])
public static string ShortenBigInt(BigInteger moneyValue)
{
string prefixes = " kMGTP";
double m2 = (double)moneyValue;
for (int i = 1; i < prefixes.Length; i++)
{
var step = Math.Pow(10, 3 * i);
if (m2 / step < 1000)
{
return String.Format("{0:F2}", (m2/step)) + prefixes[i];
}
}
return "err";
}
Although Falco's answer does work, it doesn't work for what was requested. This was the solution I was looking for and received some help from a friend on it. This solution will go until there are no more prefixes left in your string array of prefixes. If you do run out of bounds, the exception will be thrown and handled by returning "Infinity".
This solution is better due to the fact there is no crunch down to doubles/decimals within this process. This solution does not have a number cap, only limit is the amount of prefixes you make/provide.
public static string ShortenBigInt(BigInteger moneyValue)
{
if (moneyValue < 1000)
return "" + moneyValue;
try
{
string moneyAsString = moneyValue.ToString();
string prefix = prefixes[(moneyAsString.Length - 1) / 3];
BigInteger chopAmmount = (moneyAsString.Length - 1) % 3 + 1;
int insertPoint = (int)chopAmmount;
chopAmmount += 2;
moneyAsString = moneyAsString.Remove(Math.Min(moneyAsString.Length - 1, (int)chopAmmount));
moneyAsString = moneyAsString.Insert(insertPoint, ".");
return moneyAsString + " " + prefix;
}
catch (Exception exceptionToBeThrown)
{
return "Infinity";
}
}

System.DivideByZeroException on high numbers in C#

So I've been trying to write a program in C# that returns all factors for a given number (I will implement user input later). The program looks as follows:
//Number to divide
long num = 600851475143;
//initializes list
List<long> list = new List<long>();
//Defines combined variable for later output
var combined = string.Join(", ", list);
for (int i = 1; i < num; i++)
{
if (num % i == 0)
{
list.Add(i);
Console.WriteLine(i);
}
}
However, after some time the program starts to also try to divide negative numbers, which after some time ends in a System.DivideByZeroException. It's not clear to me why it does this. It only starts to do this after the "num" variable contains a number with 11 digits or more. But since I need such a high number, a fix or similiar would be highly appreciated. I am still a beginner.
Thank you!
I strongly suspect the problem is integer overflow. num is a 64-bit integer, whereas i is a 32-bit integer. If num is more than int.MaxValue, then as you increment i it will end up overflowing back to negative values and then eventually 0... at which point num % i will throw.
The simplest option is just to change i to be a long instead:
for (long i = 1; i < num; i++)
It's unfortunate that there'd be no warning in your original code - i is promoted to long where it needs to be, because there's an implicit conversion from int to long. It's not obvious to me what would need to change for this to be spotted in the language itself. It would be simpler for a Roslyn analyzer to notice this sort of problem.

What would be the shortest way to sum up the digits in odd and even places separately

I've always loved reducing number of code lines by using simple but smart math approaches. This situation seems to be one of those that need this approach. So what I basically need is to sum up digits in the odd and even places separately with minimum code. So far this is the best way I have been able to think of:
string number = "123456789";
int sumOfDigitsInOddPlaces=0;
int sumOfDigitsInEvenPlaces=0;
for (int i=0;i<number.length;i++){
if(i%2==0)//Means odd ones
sumOfDigitsInOddPlaces+=number[i];
else
sumOfDigitsInEvenPlaces+=number[i];
{
//The rest is not important
Do you have a better idea? Something without needing to use if else
int* sum[2] = {&sumOfDigitsInOddPlaces,&sumOfDigitsInEvenPlaces};
for (int i=0;i<number.length;i++)
{
*(sum[i&1])+=number[i];
}
You could use two separate loops, one for the odd indexed digits and one for the even indexed digits.
Also your modulus conditional may be wrong, you're placing the even indexed digits (0,2,4...) in the odd accumulator. Could just be that you're considering the number to be 1-based indexing with the number array being 0-based (maybe what you intended), but for algorithms sake I will consider the number to be 0-based.
Here's my proposition
number = 123456789;
sumOfDigitsInOddPlaces=0;
sumOfDigitsInEvenPlaces=0;
//even digits
for (int i = 0; i < number.length; i = i + 2){
sumOfDigitsInEvenPlaces += number[i];
}
//odd digits, note the start at j = 1
for (int j = 1; i < number.length; i = i + 2){
sumOfDigitsInOddPlaces += number[j];
}
On the large scale this doesn't improve efficiency, still an O(N) algorithm, but it eliminates the branching
Since you added C# to the question:
var numString = "123456789";
var odds = numString.Split().Where((v, i) => i % 2 == 1);
var evens = numString.Split().Where((v, i) => i % 2 == 0);
var sumOfOdds = odds.Select(int.Parse).Sum();
var sumOfEvens = evens.Select(int.Parse).Sum();
Do you like Python?
num_string = "123456789"
odds = sum(map(int, num_string[::2]))
evens = sum(map(int, num_string[1::2]))
This Java solution requires no if/else, has no code duplication and is O(N):
number = "123456789";
int[] sums = new int[2]; //sums[0] == sum of even digits, sums[1] == sum of odd
for(int arrayIndex=0; arrayIndex < 2; ++arrayIndex)
{
for (int i=0; i < number.length()-arrayIndex; i += 2)
{
sums[arrayIndex] += Character.getNumericValue(number.charAt(i+arrayIndex));
}
}
Assuming number.length is even, it is quite simple. Then the corner case is to consider the last element if number is uneven.
int i=0;
while(i<number.length-1)
{
sumOfDigitsInEvenPlaces += number[ i++ ];
sumOfDigitsInOddPlaces += number[ i++ ];
}
if( i < number.length )
sumOfDigitsInEvenPlaces += number[ i ];
Because the loop goes over i 2 by 2, if number.length is even, removing 1 does nothing.
If number.length is uneven, it removes the last item.
If number.length is uneven, then the last value of i when exiting the loop is that of the not yet visited last element.
If number.length is uneven, by modulo 2 reasoning, you have to add the last item to sumOfDigitsInEvenPlaces.
This seems slightly more verbose, but also more readable, to me than Anonymous' (accepted) answer. However, benchmarks to come.
Well, the compiler seems to think my code more understandable as well, since he removes it all if I don't print the results (which explains why I kept getting a time of 0 all along...). The other code though is obfuscated enough for even the compiler.
In the end, even with huge arrays, it's pretty hard for clock_t to tell the difference between the two. You get about a third less instructions in the second case, but since everything's in cache (and your running sums even in registers) it doesn't matter much.
For the curious, I've put the disassembly of both versions (compiled from C) here : http://pastebin.com/2fciLEMw

Cartesian product subset returning set of mostly 0

I'm trying to calculate
If we calculated every possible combination of numbers from 0 to (c-1)
with a length of x
what set would occur at point i
For example:
c = 4
x = 4
i = 3
Would yield:
[0000]
[0001]
[0002]
[0003] <- i
[0010]
....
[3333]
This is very nearly the same problem as in the related question Logic to select a specific set from Cartesian set. However, because x and i are large enough to require the use of BigInteger objects, the code has to be changed to return a List, and take an int, instead of a string array:
int PossibleNumbers;
public List<int> Get(BigInteger Address)
{
List<int> values = new List<int>();
BigInteger sizes = new BigInteger(1);
for (int j = 0; j < PixelArrayLength; j++)
{
BigInteger index = BigInteger.Divide(Address, sizes);
index = (index % PossibleNumbers);
values.Add((int)index);
sizes *= PossibleNumbers;
}
return values;
}
This seems to behave as I'd expect, however, when I start using values like this:
c = 66000
x = 950000
i = (66000^950000)/2
So here, I'm looking for the ith value in the cartesian set of 0 to (c-1) of length 950000, or put another way, the halfway point.
At this point, I just get a list of zeroes returned. How can I solve this problem?
Notes: It's quite a specific problem, and I apologise for the wall-of-text, I do hope it's not too much, I was just hoping to properly explain what I meant. Thanks to you all!
Edit: Here are some more examples: http://pastebin.com/zmSDQEGC
Here is a generic base converter... it takes a decimal for the base10 value to convert into your newBase and returns an array of int's. If you need a BigInteger this method works perfectly well with just changing the base10Value to BigInteger.
EDIT: Converted method to BigInteger since that's what you need.
EDIT 2: Thanks phoog for pointing out BigInteger is base2 so changing the method signature.
public static int[] ConvertToBase(BigInteger value, int newBase, int length)
{
var result = new Stack<int>();
while (value > 0)
{
result.Push((int)(value % newBase));
if (value < newBase)
value = 0;
else
value = value / newBase;
}
for (var i = result.Count; i < length; i++)
result.Push(0);
return result.ToArray();
}
usage...
int[] a = ConvertToBase(13, 4, 4) = [0,0,3,1]
int[] b = ConvertToBase(0, 4, 4) = [0,0,3,1]
int[] c = ConvertToBase(1234, 12, 4) = [0,8,6,10]
However the probelm you specifically state is a bit large to test it on. :)
Just calculating 66000 ^ 950000 / 2 is a good bit of work as Phoog mentioned. Unless of course you meant ^ to be the XOR operator. In which case it's quite fast.
EDIT: From the comments... The largest base10 number that can be represented given a particular newBase and length is...
var largestBase10 = BigInteger.Pow(newBase, length)-1;
The first expression of the problem boils down to "write 3 as a 4-digit base-4 number". So, if the problem is "write i as an x-digit base-c number", or, in this case, "write (66000^950000)/2 as a 950000-digit base 66000 number", then does that make it easier?
If you're specifically looking for the halfway point of the cartesian product, it's not so hard. If you assume that c is even, then the most significant digit is c / 2, and the rest of the digits are zero. If your return value is all zeros, then you may have an off-by-one error, or the like, since actually only one digit is incorrect.

toString() of int e = 0000007 omits all zeros. How can I preserve them?

I'm trying to write a program in C# that takes in an int x and decides if it has exactly 7 digits. Right now I'm using x.toString().Length == 7 to check, but I noticed that if the number starts with 0, it automatically gets omitted and I get an incorrect answer (ie the program thinks the input length is less than 7)
Is there a way to fix this? Thanks in advance.
Edit: Sorry I should have mentioned, this was a program to collect and validate the format of ID numbers (so I didn't want something like 0000001 to default to 1) Thanks for the string input suggestion, I think I'm going to try that.
If you want to preserve the input formatting, you must not convert the input to an int. You must store it in a String.
You say your program takes an int. At that point you have already lost. You need to change that interface to accept String inputs.
If you don't care about leading zeros, you're really looking for 7 digits or less. You can check for:
x.toString().Length <= 7
or better:
x < 10000000
Maybe I'm wrong, but to me, 0000001 == 1, and 1 has one digit, not seven. So that's mathematically correct behaviour.
I think you could format it as a string:
int myInt=1;
myInt.ToString("0000000");
prints:
0000001.
so you could do:
if (myInt.ToString("0000000").Length==7)
You can simply write:
int input = 5;
if(input.ToString("0000000").Length == 7)
{
//do your stuff
}
No. It is perfectly valid for a numeric literal to have leading 0s, but a) many languages consider this to be an octal literal, and b) the leading 0s don't actually exist as part of the number. If you need a string then start with a string literal.
You should use string to check length count including 0.
Then I would like to ask "Why do you want to show 0000007? For What?"
You said you're asking for a int, but I suppose you're receiving it as string:
int i = 0;
string number = Console.ReadLine();
if (Int32.TryParse(number, out i))
{
//if (i.ToString().Length == 7) // you can try this too
if (i > 999999 && i < 10000000)
{
Console.WriteLine("Have exactly 7 digits");
}
else
{
Console.WriteLine("Doesn't have exactly 7 digits");
}
}
else
{
Console.WriteLine("Not an Int32 number");
}
This way you try to cast that received number as Int32 and, so, compare its length.
You can let the number be saved as an int with the omitted zeros. but then if you want the number displayed with the zeros then you can use an if statement and a while loop. for example,
Let's assume the values are stored in a numbers array and you need them to be stored as int so you can sort them but displayed as string so you can display with the leading zeros.
int[] numbers = new int[3];
numbers[0] = 001;
numbers[1] = 002;
numbers[2] = 123;
String displayed_Number;
for (int i = 0; i < numbers.Length; i++)
{
displayed_Number = numbers[i].ToString();
if (displayed_Number.Length == 3)
{
listBox.Items.Add(displayed_Number);
}
else if (displayed_Number.Length < 3)
{
while (displayed_Number.Length < 3)
{
displayed_Number = "0" + displayed_Number;
}
listBox.Items.Add(displayed_Number);
}
}
The output is 001 002 123
That way you can maintain the zeros in the numbers when displayed. and they can be stored as int in case you have to store them as int.

Categories

Resources