.NET Conversion of very large numbers to different number base - c#

Is there any way to convert very large binary, decimal and hexadecimal numbers to each other?
I have to use it to simulate addressing process up to 256 bits.
I want to do the following conversions (and if it's possible, store them in one object)
very large binary number -> very large decimal number
very large binary number -> very large hexadecimal number
very large decimal number -> very large binary number
very large decimal number -> very large hexadecimal number
very large hexadecimal number -> very large binary number
very large hexadecimal number -> very large decimal number
very large binary number -> string
very large decimal number -> string
very large hexadecimal number -> string
The possibility of splitting and joining very large binary numbers is very important.
If it's possible, I would use a class supported solution, and avoid manual conversion from one number base to another using byte[] type.
I've tried the BigInteger class, it can store very large numbers, but can't convert them to another number base.

Solution by Andrew Jonkers :
//Convert number in string representation from base:from to base:to.
//Return result as a string
public static String Convert(int from, int to, String s)
{
//Return error if input is empty
if (String.IsNullOrEmpty(s))
{
return ("Error: Nothing in Input String");
}
//only allow uppercase input characters in string
s = s.ToUpper();
//only do base 2 to base 36 (digit represented by characters 0-Z)"
if (from < 2 || from > 36 || to < 2 || to > 36)
{ return ("Base requested outside range"); }
//convert string to an array of integer digits representing number in base:from
int il = s.Length;
int[] fs = new int[il];
int k = 0;
for (int i = s.Length - 1; i >= 0; i--)
{
if (s[i] >= '0' && s[i] <= '9') { fs[k++] = (int)(s[i] - '0'); }
else
{
if (s[i] >= 'A' && s[i] <= 'Z') { fs[k++] = 10 + (int)(s[i] - 'A'); }
else
{ return ("Error: Input string must only contain any of 0-9 or A-Z"); } //only allow 0-9 A-Z characters
}
}
//check the input for digits that exceed the allowable for base:from
foreach(int i in fs)
{
if (i >= from) { return ("Error: Not a valid number for this input base"); }
}
//find how many digits the output needs
int ol = il * (from / to+1);
int[] ts = new int[ol+10]; //assign accumulation array
int[] cums = new int[ol+10]; //assign the result array
ts[0] = 1; //initialize array with number 1
//evaluate the output
for (int i = 0; i < il; i++) //for each input digit
{
for (int j = 0; j < ol; j++) //add the input digit
// times (base:to from^i) to the output cumulator
{
cums[j] += ts[j] * fs[i];
int temp = cums[j];
int rem = 0;
int ip = j;
do // fix up any remainders in base:to
{
rem = temp / to;
cums[ip] = temp-rem*to; ip++;
cums[ip] += rem;
temp = cums[ip];
}
while (temp >=to);
}
//calculate the next power from^i) in base:to format
for (int j = 0; j < ol; j++)
{
ts[j] = ts[j] * from;
}
for(int j=0;j<ol;j++) //check for any remainders
{
int temp = ts[j];
int rem = 0;
int ip = j;
do //fix up any remainders
{
rem = temp / to;
ts[ip] = temp - rem * to; ip++;
ts[ip] += rem;
temp = ts[ip];
}
while (temp >= to);
}
}
//convert the output to string format (digits 0,to-1 converted to 0-Z characters)
String sout = String.Empty; //initialize output string
bool first = false; //leading zero flag
for (int i = ol ; i >= 0; i--)
{
if (cums[i] != 0) { first = true; }
if (!first) { continue; }
if (cums[i] < 10) { sout += (char)(cums[i] + '0'); }
else { sout += (char)(cums[i] + 'A'-10); }
}
if (String.IsNullOrEmpty(sout)) { return "0"; } //input was zero, return 0
//return the converted string
return sout;
}

I had the same issue once. I wrote simple method which changes array of decimal numbers to array of binary numbers.
private int[] ConvertDecimalCharArrayToBinaryCharArray(int[] decimalValues)
{
List<int> result = new List<int>();
bool end = false;
while (end == false)
{
result.Add(decimalValues[decimalValues.Length - 1] % 2);
int previous = 0;
bool allzeros = true;
for (int i = 0; i < decimalValues.Length; i++)
{
var x = decimalValues[i];
if (x != 0)
{
allzeros = false;
}
if (allzeros && i == decimalValues.Length - 1)
{
end = true;
}
var a = (x + previous) / 2;
if ((x + previous) % 2== 1)
{
previous = 10;
}
else
{
previous = 0;
}
decimalValues[i] = a;
}
}
result.RemoveAt(result.Count - 1);
result.Reverse();
return result.ToArray();
}

Related

Is there a dynamic way to split 100 into different values?

I am stuck in a scenario which is complex for me to implement. Scenario is : I have rows in excel sheet which is dynamic . sometimes it could be 2, sometimes 5, sometimes 12 means any number of rows could be there. i need to assign different unique values to each available row in such a way that their sum should be equal to 100. Example : if i have 2 rows i can assign values 65 and 35 but not 50 to both as the value needs to be unique. similarly if i have 4 rows i need to assign values like 20,30, 27, 23 .Need a c# code for this.
How can i do this?
There are many ways you could generate different random numbers for each row. The way I generated the numbers was with DateTime.Now.Second and DateTime.Now.Minute. To ensure that the numbers never go over 100, you can subtract from the maximum number in the row. This is the general idea:
`
public static ulong CapAtNumber(ulong num, ulong cap) {
while(num>cap)
{
num = (num / 2) - 2;
if (num < 3)
{
num += (Convert.ToUInt64(DateTime.Now.Minute) + Convert.ToUInt64(DateTime.Now.Second) / 2);
}
}
return num;
}
This is an example of how you would find the maximum. I used the Math group to check for maximums among twoulong` numbers. The numbers are A B C D E F, and so on, and I group them into AB CD EF to find the maximum between the groups. The array size gets cut in half each time until the array size is 1. When the array size is 1, the number in the array is the maximum.
public static ulong[] FindTheMaxOfArray(ulong[] arg)
{
bool repeat = true;
ulong checknumber = 100;
while(repeat == true)
{
if (arg.Length % 2 == 0)
{
var halflist = new ulong[arg.Length / 2];
for (int z = 0; z < arg.Length / 2; z += 2)
{
halflist[z] = Math.Max(arg[z], arg[z + 1]);
if (
halflist.Length == 1)
{
repeat = true;
arg = new ulong[halflist.Length];
arg = halflist;
}
else { repeat = false;
checknumber = halflist[0]; }
}
}
else
{
var halflist = new ulong[arg.Length + 1 / 2];
for (int z = 0; z < halflist.Length; z++)
{
if (z % 2 != 0)
{
if (z != halflist.Length - 2)
{
halflist[z] = Convert.ToUInt64(Math.Max(Math.Max(arg[z], arg[z + 1]), arg[z + 2]));
}
else { halflist[z] = Convert.ToUInt64(Math.Max(arg[z], arg[z + 1])); }
}
}
if (halflist.Length == 1)
{
repeat = true;
arg = new ulong[halflist.Length];
arg = halflist;
}
else { checknumber = halflist[0];
repeat = false;
}
}
}
for(int z=0; z<arg.Length; z++)
{
if (arg[z] == checknumber)
{
arg[z] = CapAtNumber(arg[z], arg[z] - 20);
}
}
return arg;
}
if you want to ensure that there are no repeats, you can create a method to check for that. Each number in the foreach loop is checking with the numbers in the for loop. Since these are the same arrays, there has to be at least one repeat that happens naturally. Everything except this part seems to run smoothly. Here is an example
public static ulong[] Checkforrepeats(ulong[] args)
{
ulong repeatednumber = 1000;
int repeat = -1;
foreach( ulong num in args)
{
for(int z = 0; z<args.Length; z++)
{
if(z == 0)
{ repeat = -1; }
if(num ==args[z])
{
repeat += 1; //repeat was set to -1 to counter act the guaranteed repeat that will happen
}
if (repeat == 2)
{
args[z] += 2;
args[z - 1] -= 2;
}
}
}
return args;
}

How to get integers to an array (from integer i to integer j). c#

I want to store integers(in an array or anything) that in range of int "i" and int "j".
eg:-Think, "int i = 1" and "int j = 10".I want to store integers from 1 and 10.
So that (1,2,3,4,5,6,7,8,9,10)
Because I want to answer to HackerRank "Beautiful Days at the Movies".
link below.
https://www.hackerrank.com/challenges/beautiful-days-at-the-movies/problem?isFullScreen=false
here is my code and it a garbage.
static int beautifulDays(int i, int j, int k) {
var total = 0;
for(var a = i; a <= j; a++ )
{
if (a != 0)
{
int ri = Reverse(i);
int rj = Reverse(j);
var ra = Reverse(a);
if((ra/k) % 1 == 0)
{
total++;
}
if((rj/k) % 1 == 0)
{
total++;
}
if((ri/k) % 1 == 0)
{
total++;
}
}
return total;
}
return total;
}
public static int Reverse(int inval)
{
int result = 0;
do
{
result = (result * 10) + (inval % 10);
inval = inval / 10;
}
while(inval > 0);
return result;
}
simply, can you give me the answer of HackerRank "Beautiful Days at the Movies".
link below.
https://www.hackerrank.com/challenges/beautiful-days-at-the-movies/problem?isFullScreen=false
Using Java you can easily stream a range of numbers with IntStream, then map the reverse function for each value, then filter those that fulfils the condition and count. With streams you don't need to store, you can get straight to the answer.
IntUnaryOperator reverse = (opperand) -> {
int reversed = 0;
int num = opperand;
while (num != 0) {
int digit = num % 10;
reversed = reversed * 10 + digit;
num /= 10;
}
return Math.abs(opperand - reversed);
};
return (int) IntStream.rangeClosed(i, j).map(reverse)
.filter(v -> v % k == 0).count();

Assistance in Validating Binary

Need help, cant figure out how to validate this as binary. Any help appreciated I know I am a noob.
Tried this... didn't work so well
// } while (binaryStringIsValid(binaryStr) == false);
//static bool binaryStringIsValid(string binaryStr)
//{
// bool valid = false;
// foreach (char ch in binaryStr)
// {
// if (ch != '0' && ch != '1')
// {
// Console.WriteLine("String Is Invalid");
// }
// }valid = binaryStr.Length < 9;
// return valid;
//}
{
int digits = 0;
string binaryStr = "";
int sum = 0;
int remainder;
int po2 = 0;
Console.WriteLine("Enter a valid binary string: ");
digits = Convert.ToInt32(Console.ReadLine());
while (digits > 0)
{
remainder = digits % 10;
sum = sum + remainder * Convert.ToInt32(Math.Pow(2, po2));
po2 = po2 + 1;
digits = digits / 10;
}
Console.WriteLine("Your binary string is equal to the decimal
number: " + sum);
Console.ReadKey();
}
I need to make sure it has only 0's and 1's and is <9 characters long.
Check this code
public bool IsBinary(string input) => new Regex("^[01]{1,9}$").IsMatch(input);

Serial key generation xor string encryption

When I do an xor on a string I get special characters
private void btnEncryptDecrypt_Click(object sender, EventArgs e)
{
byte[] bytes = Encoding.UTF8.GetBytes(keyTextBox.Text);
textTextBox.Text = string.Empty;
foreach (byte i in bytes)
{
byte c = Convert.ToByte(i ^ Convert.ToByte(textBox1.Text));
textTextBox.Text = textTextBox.Text + Convert.ToChar(c);
}
}
62FA7AC4 1234567890 xor to !%QV VT#7&%$#"! /.'
I want to use it for serial key generation with only alphanumeric characters
I want to pass "62FA7AC4", a date and a number between 0 and 5000 and a few random dummy numbers
Input will be "62FA7AC4"+"2500"+"21/05/2018"
Output should be something like "5QBK-J4D1-8CF6-5MW2-78FZ-2FPL-4S6S-CTGB"
What am I doing Wrong?
Try working with numbers, not strings:
using System.Numerics;
...
// Let's use BigInteger for arbitrary long values
BigInteger left = BigInteger.Parse("62FA7AC4", NumberStyles.HexNumber);
BigInteger right = BigInteger.Parse("1234567890", NumberStyles.HexNumber);
string result = (left ^ right).ToString("X");
Console.Write(result);
So you have
1256AC0254
Edit: As far as I can see you want alphanumeric (i.e. Base 36 == 26 letters + 10 digits output). You can use the same approach: operate with integer(s), not string(s)
private static Random s_Random = new Random();
...
BigInteger value = BigInteger.Parse(
"0" + // we don't want negative values
"62FA7AC4" + // header
s_Random.Next(5001).ToString("0000") + // random in [0..5000] range
DateTime.Today.ToString("ddMMyyyy"), // Date like 21052018
NumberStyles.HexNumber);
Then do any xor (if you like):
value ^= some_secret_value;
Finally represent the value in base 36:
private static String ToBase36(BigInteger value) {
List<char> list = new List<char>();
for (int index = 0; value > 0; value /= 36, index++) {
if (index > 0 && index % 4 == 0)
list.Add('-');
BigInteger v = value % 36;
list.Add(v < 10 ? (char)('0' + v) : (char) ('A' + v - 10));
}
list.Reverse();
return string.Concat(list);
}
Test:
BigInteger value = BigInteger.Parse(
"0" +
"62FA7AC4" +
"2500" +
DateTime.Today.ToString("ddMMyyyy"),
NumberStyles.HexNumber);
string result = ToBase36(value);
Console.Write(result);
Outcome:
2443-WNC5-AVBB-M32W
Edit 2: To restore the original number
private static BigInteger FromBase36(string value) {
BigInteger result = 0;
BigInteger power = 1;
for (int i = value.Length - 1; i >= 0; --i) {
char item = value[i];
if (item >= '0' && item <= '9') {
result += power * (item - '0');
power *= 36;
}
else if (item >= 'A' && item <= 'Z') {
result += power * (item - 'A' + 10);
power *= 36;
}
else if (item >= 'a' && item <= 'z') {
result += power * (item - 'a' + 10);
power *= 36;
}
}
return result;
}
e.g.
BigInteger value = BigInteger.Parse(
"0" +
"62FA7AC4" +
"2500" +
DateTime.Today.ToString("ddMMyyyy"),
NumberStyles.HexNumber);
string result = ToBase36(value);
BigInteger back = FromBase36(result);
Console.WriteLine(string.Join(Environment.NewLine, value, result, back));
Outcome:
467412447575903165554712
2443-WNC5-AVBB-M32W
467412447575903165554712

Special Counters

I`m trying to create a special counter in C# ... I mean the counter will be consisting of characters not numbers.
I have a char[] of size 3:
char[] str = new char[strSize];
int i = 0;
int tmpSize = strSize - 1;
int curr;
while(!isEqual(str,finalStr,strSize))
{
str[strSize] = element[i % element.Length];
i++;
if (str[strSize] == element[element.Length - 1])
{
int j = strSize - 1;
if (j > 0)
{
j--;
int tmpCntr = j+1;
curr = getCurrentID(str[tmpCntr]);
str[tmpCntr] = element[(curr + 1) % element.Length];
while (str[tmpCntr] == element[0] && (i % element.Length > 0) && tmpCntr < 0)
{
tmpCntr--;
curr = getCurrentID(str[tmpCntr]);
str[tmpCntr] = element[(curr + 1) % element.Length];
}
}
}
}
if the strSize < 3 the application works fine and gives accurate output. If the strSize >= 3, the application goes in infinite loop!
Need help.
if this is hard this way, I would need a way to create a numerical counter and I`ll work on it to suite my application.
You haven't shown what half of your methods or parameters are.
Personally I would take a different approach. I would use an iterator block to make it easy to return an IEnumerable<string>, and internally just keep an integer counter. Then you just need to write a method to convert a counter value and "alphabet of digits" into a string. Something like this:
public static IEnumerable<string> Counter(string digits, int digitCount)
{
long max = (long) Math.Pow(digits.Length, digitCount);
for (long i = 0; i < max; i++)
{
yield return ConvertToString(i, digits, digitCount);
}
}
Another alternative is to do the same thing with LINQ, if a range of int is enough:
public static IEnumerable<string> Counter(string digits, int digitCount)
{
int max = (int) Math.Pow(digits.Length, digitCount);
return Enumerable.Range(0, max)
.Select(i => ConvertToString(i, digits, digitCount));
}
In either case, you just iterate over the returned sequence to get appropriate counter values.
With those in place, you just need to implement ConvertToString - which would probably be something like this:
public static string ConvertToString(long value, string digits, int digitCount)
{
char[] chars = new char[digitCount];
for (int i = digitCount - 1 ; i >= 0; i--)
{
chars[i] = digits[(int)(value % digits.Length)];
value = value / digits.Length;
}
return new string(chars);
}
Here's a test program showing it all working:
using System;
using System.Collections.Generic;
using System.Linq;
class Test
{
static void Main()
{
// Show the first 10 values
foreach (string value in Counter("ABCD", 3).Take(10))
{
Console.WriteLine(value);
}
}
public static IEnumerable<string> Counter(string digits, int digitCount)
{
long max = (long) Math.Pow(digits.Length, digitCount);
for (long i = 0; i < max; i++)
{
yield return ConvertToString(i, digits, digitCount);
}
}
public static string ConvertToString(long value,
string digits,
int digitCount)
{
char[] chars = new char[digitCount];
for (int i = digitCount - 1 ; i >= 0; i--)
{
chars[i] = digits[(int)(value % digits.Length)];
value = value / digits.Length;
}
return new string(chars);
}
}
Output:
AAA
AAB
AAC
AAD
ABA
ABB
ABC
ABD
ACA
ACB

Categories