Converting non digit text to double and then back to string - c#

I have a unique situation where I have to write code on top of an already establish platform so I am trying to figure out a hack to make something work.
The problem I have is I have a user defined string. Basically naming a signal. I need to get this into another program but the only method available is within a double value. Below is what I have tried but not been able to get it to work. I tried converting the string to byte array and then creating a new string by looping the bytes. Then I convert this string to a Double. Then use BitCoverter to get it back to byte array and then try to get the string.
Not sure if this can even be achieve. Any ideas?
string signal = "R3MEXA";
string newId = "1";
byte[] asciiBytes = System.Text.Encoding.ASCII.GetBytes(signal);
foreach (byte b in asciiBytes)
newId += b.ToString();
double signalInt = Double.Parse(newId);
byte[] bytes = BitConverter.GetBytes(signalInt);
string result = System.Text.Encoding.ASCII.GetString(bytes);

Asuming your string consists of ASCII characters (7Bit):
Convert your string into a bit-Array, seven bits per character.
Convert this bit-array into a string of digits, using 3 bits for each digit. (there are digits 0..7)
Convert this string of digits to a double number.

You initially set newId to "1", which means when you're doing later conversion, you're not going to get the right output unless to account for the "1" again.

It doesn't work, because if you convert it back you don't know the length of a byte.
So I made every byte to a length of 3.
string signal = "R3MEXA";
string newId = "1";
byte[] asciiBytes = System.Text.Encoding.ASCII.GetBytes(signal);
foreach (byte b in asciiBytes)
newId += b.ToString().PadLeft(3,'0'); //Add Zero, if the byte has less than 3 digits
double signalInt = Double.Parse(newId);
//Convert it back
List<byte> bytes = new List<byte>(); //Create a list, we don't know how many bytes will come (Or you calc it: maximum is _signal / 3)
//string _signal = signalInt.ToString("F0"); //Maybe you know a better way to get the double to string without scientific
//This is my workaround to get the integer part from the double:
//It's not perfect, but I don't know another way at the moment without losing information
string _signal = "";
while (signalInt > 1)
{
int _int = (int)(signalInt % 10);
_signal += (_int).ToString();
signalInt /= 10;
}
_signal = String.Join("",_signal.Reverse());
for (int i = 1; i < _signal.Length; i+=3)
{
byte b = Convert.ToByte(_signal.Substring(i, 3)); //Make 3 digits to one byte
if(b!=0) //With the ToString("F0") it is possible that empty bytes are at the end
bytes.Add(b);
}
string result = System.Text.Encoding.ASCII.GetString(bytes.ToArray()); //Yeah "R3MEX" The "A" is lost, because double can't hold that much.
What can improved?
Not every PadLeft is necessary. Work from back to front and if the third digit of a byte is greater than 2, you know, that the byte has only two digits. (Sorry for my english, I write an example).
Example
194 | 68 | 75 | 13
194687513
Reverse:
315786491
31 //5 is too big 13
57 //8 is too big 75
86 //4 is too big 68
491 //1 is ok 194

Related

Storing numbers larger than Big integer C#

I am having a really hard time finding a way to store massive prime numbers in c#. I tried everything but nothing worked out for me. For example. How can I store this number.
0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF
Do you know how or what an external library that could store that?
Thanks!!!
The size of an integer representable by BigInteger is effectively only constrained by the maximum addressable memory of the program if not the computer itself. You can parse one by using BigInteger.Parse or BigInteger.TryParse and passing NumberStyles.HexNumber (minus the "0x" part of the string).
A note about Parse, if the first digit is "8" or higher, that will result in the first bit of the number's binary representation being a 1. Signed integers interpret this as being a negative number, so your resulting number will not only be a negative number, but it will be very different than the equivalent positive number's binary representation. To avoid this, prepend a "0" to the input string.
You can "store" it by either converting it back into a string with ToString or by converting it into a byte array with ToByteArray, appropriately enough.
var input = "0FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF";
var hugeNumber = BigInteger.Parse(input, NumberStyles.HexNumber);
var hugeNumberString = hugeNumber.ToString();
var hugeNumberBytes = hugeNumber.ToByteArray();
// You can reload the byte array by simply passing it to the `BigInteger` constructor.
var hugeNumberReconstructed = new BigInteger(hugeNumberBytes);
BigInteger does it
var bytes = new List<Byte>();
string num = #"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF";
for (int i = 0; i < num.Length; i+=2) {
var b = num.Substring(i, 2);
var x = Convert.ToByte(b, 16);
bytes.Add(x);
}
var bn = new System.Numerics.BigInteger(bytes.ToArray());
debugger shows
bn {-1570566720338582667927906308486331020678313192057614971584760731901058647139518057241123644094401330702204896434749395740948521204256830813802793411121615133171266951981018749121361010262657119536344690188227760522346385933065780960593402202465448470021036386883323238183599243975089536777184470963161425724987363228043371573877576452029605409494617533656095430483815839481907153364288401182596736380740919039955960610857082518546213313320880567980770439331102549009223218208548749082963734827189358268113429507100272583973032847664061854471533479116667574516065732839447648992011110538140617869829020597826272370250406178983259310517449686885092778023735816105275313156168057770834629675841435934157964159733407369373150569643832403368714414248477830355864648343905813412169307812679570071021264327268776159178258126189105355201727008666110957901070869422442964928204432497893639569923030486663520936478372141324725647779388824026436194349030123028127183590807988699910718883036274092296195738801238932240607706512065663168315105279062647762457541689320199801400963441351542207060400661407720411212987665329161135568453084989958577002926963319659401211071077577114413531153489686602746402174695962726389204418249748806498154334309175313426956505725867430885326612261827698634725487008721538567095488663671271012738141457858408427283049274115742675742516750037999118278841924003978633759158117873692177310838874149259276441739874499926101302480541938686564170604159164760763295532542904951250793468087996706862009509879288767160917718363858884333087557922625562601699376322568867851374429539180956730361131113520484694955462251349689481650791574910892992752905760719949241290478195310550499570804467728132132006347697735259131798874824194406553202473938274024972466003838104776740077783578318451208991087791302742074840248125227009}
BigInteger, but you need to add a Zero at the begining of the hexadecimal string number, to avoid get a negative number
public Class1()
{
var cadNumber =
"0FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF";
decimal.TryParse(
cadNumber
,out decimal numberDecimal);
var numberBigInteger = BigInteger.Parse(cadNumber, NumberStyles.AllowHexSpecifier);
var numberLong = long.Parse(cadNumber, NumberStyles.AllowHexSpecifier);
}

Format string with decimal

I am trying to take a string that may or may not contain a '.' to x amount of characters removing the "decimal point" as well. the result will ultimately be converted to a signed integer. I will also always need to the 1/10 decimal (ie 10 will become 100, 1 will become 10, etc...) I would like to just format the string without converting to an integer until the very end.
Example
if my incoming string is
9.86
I want 98 as a string ( i don't care about rounding up or anything)
if i get 9
I want 90
if i get -100
i want -1000
if i get -95.353
i want -953
string.Format("{0:d}", (int)9.015*10);
If you want a rounded result, replace the Cast
Edit: But I missed the "string" part. Verbose code below
var input = "9.86";
var len = input.IndexOf('.');
var result = "";
if (len > 0)
{
result = input.Substring(0, len);
result += input.Substring(len + 1, 1);
}
else
{
result = input + "0";
}
If you are essentially multiplying by ten the number contained in the string and dropping decimal places after the first, then you would be better off casting the string as a decimal and then doing the conversion and casting that number as an integer. Otherwise you will have to write a large set of mathematical rules on how to modify your string based on a particular type of input.
string[] input = {"9.86", "9", "-100", "-95.3"};
List<int> intNums = new List<int>();
foreach (string s in input)
{
decimal number;
if (Decimal.TryParse(s, out number))
{
number = number * 10;
intNums.Add((int)number);
}
}
Output:
[0] 98 int
[1] 90 int
[2] -1000 int
[3] -953 int

how to cast doubles from char array

I am shifting in 3 chars from serial port every 3rd char is a double that i split up for the port, so now i need to put it back to gether.
(Value before sending = 0x3F3400 or 0.703125)
char[0] = 0x3F (msb)
char[1] = 0x34
char[2] = 0x00 (lsb)
double total = (char[0] << 16)+(char[1] << 8)+(char[2]); // this part did not work
Pls advise how to rebuild this, I dont understand doubles well enough, I cannot even tell which part of a double is the decimal point or - sign
thanks!
I can't get yor value, but as help can advice you to use BitConverter and byte array like this:
var v = new byte[8];
v[7] = 0x3F;
v[6] = 0x34;
v[5] = 0x00;
double total = BitConverter.ToDouble(v, 0);
Console.WriteLine(total.ToString("0.0000000000000"));

replacing 1st digit with second digit in a byte

What I'm trying to do is loop through the values in the byte array getting the first digit of each value and swapping its place with the second digit, so 35 would be 53 and 24 would be 42.. I can almost do this but i have to convert everything to strings and that seems a little overkill
I've tried it for a while but so far I've only figured that I can convert everything to a string and then work on them, just seems a little clunky..
It sounds like you want to swap the high and low nibble in each byte.
0x35; // High nibble = 3, Low Nibble = 5
To do this, you want to shift the high nibble right 4 bits (to make it the low nibble), and shift the low nibble left 4 bits (to make it the high nibble).
var ar = new byte[] { 0x35, 0x24 };
for (int i=0; i<ar.Length; i++) {
byte b = ar[i];
b = (b>>4) | ((b&0x0F)<<4);
ar[i] = b;
}
byte nmbBase =16; //or any other 10 for decimal
byte firstDigit = number /nmbBase;
byte secondDigit = number % nmbBase;
number = secondDigit*numberBase + firstDigit;
This is from cellphone,sorry for any mistakes. You should get in which direction you should go.

Calculating the number of bits in a Subnet Mask in C#

I have a task to complete in C#. I have a Subnet Mask: 255.255.128.0.
I need to find the number of bits in the Subnet Mask, which would be, in this case, 17.
However, I need to be able to do this in C# WITHOUT the use of the System.Net library (the system I am programming in does not have access to this library).
It seems like the process should be something like:
1) Split the Subnet Mask into Octets.
2) Convert the Octets to be binary.
3) Count the number of Ones in each Octet.
4) Output the total number of found Ones.
However, my C# is pretty poor. Does anyone have the C# knowledge to help?
Bit counting algorithm taken from:
http://www.necessaryandsufficient.net/2009/04/optimising-bit-counting-using-iterative-data-driven-development/
string mask = "255.255.128.0";
int totalBits = 0;
foreach (string octet in mask.Split('.'))
{
byte octetByte = byte.Parse(octet);
while (octetByte != 0)
{
totalBits += octetByte & 1; // logical AND on the LSB
octetByte >>= 1; // do a bitwise shift to the right to create a new LSB
}
}
Console.WriteLine(totalBits);
The most simple algorithm from the article was used. If performance is critical, you might want to read the article and use a more optimized solution from it.
string ip = "255.255.128.0";
string a = "";
ip.Split('.').ToList().ForEach(x => a += Convert.ToInt32(x, 2).ToString());
int ones_found = a.Replace("0", "").Length;
A complete sample:
public int CountBit(string mask)
{
int ones=0;
Array.ForEach(mask.Split('.'),(s)=>Array.ForEach(Convert.ToString(int.Parse(s),2).Where(c=>c=='1').ToArray(),(k)=>ones++));
return ones
}
You can convert a number to binary like this:
string ip = "255.255.128.0";
string[] tokens = ip.Split('.');
string result = "";
foreach (string token in tokens)
{
int tokenNum = int.Parse(token);
string octet = Convert.ToString(tokenNum, 2);
while (octet.Length < 8)
octet = octet + '0';
result += octet;
}
int mask = result.LastIndexOf('1') + 1;
The solution is to use a binary operation like
foreach(string octet in ipAddress.Split('.'))
{
int oct = int.Parse(octet);
while(oct !=0)
{
total += oct & 1; // {1}
oct >>=1; //{2}
}
}
The trick is that on line {1} the binary AND is in sence a multiplication so multiplicating 1x0=0, 1x1=1. So if we have some hypothetic number
0000101001 and multiply it by 1 (so in binary world we execute &), which is nothig else then 0000000001, we get
0000101001
0000000001
Most right digit is 1 in both numbers so making binary AND return 1, otherwise if ANY of the numbers minor digit will be 0, the result will be 0.
So here, on line total += oct & 1 we add to tolal either 1 or 0, based on that digi number.
On line {2}, instead we just shift the minor bit to right by, actually, deviding the number by 2, untill it becomes 0.
Easy.
EDIT
This is valid for intgere and for byte types, but do not use this technique on floating point numbers. By the way, it's pretty valuable solution for this question.

Categories

Resources