complex string to double conversion - c#

I have strings in a XML file that ment to be doubles (or float) such as:
<VIPair>
<voltage>+100mV</voltage>
<current>+1.05pA</current>
</VIPair>
<VIPair>
<voltage>+5.00mV</voltage>
<current>+0.0035nA</current>
</VIPair>
The first pair will be "0.1" Volt and "0.00000000000105" Ampere.
The second pair would be "0.005" Volt and "0.000000000035" Ampere.
How can I convert them to double of float in C#?
Thanks.
P.S: I already can read them from xml file and at the moment I retrive them as string.

Try with this:
// Read string (if you do not want to use xml)
string test = "<voltage>+100mV</voltage>";
string measure = test.Substring(test.IndexOf('>')+1);
measure = measure.Substring(0, measure.IndexOf('<')-1);
// Extract measure unit
string um = measure.Substring(measure.Length - 1);
measure = measure.Substring(0, measure.Length - 1);
// Get value
double val = Double.Parse(measure);
// Convert value according to measure unit
switch (um)
{
case "G": val *= 1E9; break;
case "M": val *= 1E6; break;
case "k": val *= 1E3; break;
case "m": val /= 1E3; break;
case "u": val /= 1E6; break;
case "n": val /= 1E9; break;
case "p": val /= 1E12; break;
}

Hi here is another version of what Marco has written.
string str = "1pV";
double factor;
double value;
switch (str[str.Length-2])
{
case 'M': factor = 1E6; break;
case 'm': factor = 1E-3; break;
case 'n': factor = 1E-9; break;
case 'p': factor = 1E-12; break;
default:
factor = 1; break;
}
value = double.Parse(str.Substring(0,str.Length-2)) * factor;
Assuming that the html text is already available to you. I have tried to do the same thing with one substring, switch case with characters instead of strings(This is a bit faster to comparing strings) and a double.parse. Hope someone comes up with a better version than this.

Remove the suffix string mV and nA using string.Substring or string.Remove() method and use double.TryParse() method to parse string to double.

If your values always have 2 chars on the end you could simple remove these and parse the number.
var newstring = fullstring.Substring(0, fullstring.Length - 2);
var number = double.Parse(newstring);

Related

I'm trying to make a calculator but I keep getting CS0165 and I'm confused as to why

The Console.Writeline(result); at the end returns error CS0165 Use of unassigned local variable 'result' and I don't know why. Would appreciate an explanation as I'm a complete beginner. Like I said in the title, I'm trying to build a calculator.
char Operator;
double firstNumber;
double secondNumber;
Console.WriteLine("Enter the first number");
string firstNumberAsText = Console.ReadLine();
Console.WriteLine("Enter the second number");
string secondNumberAsText = Console.ReadLine();
Console.WriteLine(#"Enter a math operation. '+' for addition, '-' for subtraction, '*' for multiplication, '/' for division, '%' for remainder and '^' for power");
string mathOperator = Console.ReadLine();
firstNumber = Convert.ToDouble(firstNumberAsText);
secondNumber = Convert.ToDouble(secondNumberAsText);
Operator = Convert.ToChar(mathOperator);
double result;
switch (Operator)
{
case '+':
result = firstNumber + secondNumber;
break;
case '-':
result = firstNumber - secondNumber;
break;
case '*':
result = firstNumber * secondNumber;
break;
case '/':
result = firstNumber / secondNumber;
break;
case '%':
result = firstNumber % secondNumber;
break;
case '^':
result = Math.Pow(firstNumber, secondNumber);
break;
default:
Console.WriteLine("unrecognised operator: " + Operator);
break;
}
Console.WriteLine(result);
Console.ReadKey();
The error itself tells you what's wrong:
Error CS0165: Use of unassigned local variable 'result'
This means that you're trying to use a variable that may not have been initialized yet. Notice that it isn't initialized it when it's declared, and it isn't assigned a value in the default: case in the switch statement.
So there are two ways to solve this:
1) Initialize the variable when you declare it
double result = 0;
2) Or, make sure every possible code path (including then default switch case) assigns a value to it before it's used
default:
result = 0;
Console.WriteLine($"unrecognised operator: {Operator}");
break;
In the case of an unrecognised operator, the result variable would be undefined when trying to do the Console.WriteLine(). You either need to set it to a value when catching the default behaviour, or initialize it before the switch.

Parsing routine for over-sign characters relatively slow

I am trying to make the enclosed subroutine more performant using NET framework 4.6.1 although I will eventually port it to net core 2.2 .
It may run up to 250,000 times when parsing a file.
Using Visual Studio Performance Analyzer I see this routine seems to have a fairly high relative cost in the whole parsing process.
The code is part of a parsing program whose input is a binary file that contains some very old record formats that contain over-signed numbers.
Over-signed Numbers (background)
Instead of a minus sign and in order to save space the last digit is made a letter if the number is negative. Its a very old standard dating back to when computers had limited memory and fixed width records were required for performance.
When parsing I need to convert the last letter back to a number and make the number negative
Some examples of input and output of the routine
00056K = -562
00032N = -325
Current Code (slow)
private int ConvertOverSign(string overSignedString)
{
switch(overSignedString.Substring(overSignedString.Length -1,1))
{
case " ":
return 0;
case "J":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "1");
case "K":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "2");
case "L":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "3");
case "M":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "4");
case "N":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "5");
case "O":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "6");
case "P":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "7");
case "Q":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "8");
case "R":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "9");
case "!":
return -Convert.ToInt32(overSignedString.Substring(0,overSignedString.Length -1) + "0");
default:
return Convert.ToInt32(overSignedString);
}
}
Not sure the below solution is fully equivalent to yours, but at least should give you a hint on how to make a very fast string-to-number parser.
private int ConvertOverSign(string overSignedString)
{
if (overSignedString == " ") return 0;
int value = 0;
for (int i = 0; i < overSignedString.Length; i++)
{
char ch = overSignedString[i];
switch (ch)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
value = value * 10 + (ch - 0x30);
break;
case '!':
value *= 10;
return -value;
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
value = value * 10 + (ch - 'I');
return -value;
}
}
return value;
}
Bear in mind that string manipulations (e.g. Substring) are typically heavy if you need performance.
Switch over the indexed character. Substring is actually alocating a new string and that is slow:
switch (overSignedString[Length - 1])
{
case ' ':
return 0;
case "J":
return ...
You might want to read this to see if its worth parsing the string inside each case avoiding Convert. There are faster ways.
Your method is slow because it generates a lot of string garbage.
You could improve it by comparing characters instead of strings, and perform multiplication of the resulting integer instead of appending strings and using a lookup instead of a switch:
private Dictionary<char, int> _additions = new Dictionary<char, int>
{
{ '!', 0 },
{ 'J', 1 },
{ 'K', 2 },
{ 'L', 3 },
{ 'M', 4 },
{ 'N', 5 },
{ 'O', 6 },
{ 'P', 7 },
{ 'Q', 8 },
{ 'R', 9 },
};
private int ConvertOverSign(string overSignedString)
{
var lastChar = overSignedString[overSignedString.Length -1];
if (lastChar == ' ')
{
return 0;
}
if (!_additions.TryGetValue(lastChar, out int addition))
{
return Convert.ToInt32(overSignedString);
}
var result = (Convert.ToInt32(overSignedString.Substring(0, overSignedString.Length - 1)) * -10) - addition;
return result;
}

C# Convert Alphanumeric phone number

I've been working on this issue for awhile and I've been stuck so I hope someone can push me in the right direction. I have a c# console application that will take in a string and verify that it contains only 0-9, a-z, A-Z, and -.
My issue that I'm having is that I need to convert any letters in the phone number to their respective number. So if I input 1800-Flowers, it will output as 1800-3569377. I have my methods defined:
I'm not looking for the solutions here (this is homework), but I'm looking for a push in the right direction. Do I need to convert the string to a char array to break up each individual character, and then use that in the convert method to switch any letter into a number?
There are certainly a lot of solutions here. Since you're already using Regex, you could approach it in a basic way:
num = Regex.Replace(num, #"[abcABC]", "2");
num = Regex.Replace(num, #"[defDEF]", "3");
//....
or you could create a Dictionary<string,char> and run through each char and convert it to the mapped character. Something like :
var dict = new Dictionary<string, char>();
dict.Add("abcABC",'2');
//...
foreach(char c in num.Where(char.IsLetter))
{
var digit = dict.First(d => d.Key.Contains(c)).Value;
num = num.Replace(c, digit);
}
Like you said, the LINQ here is splitting the string to a char array, and looping through ones that are letters
Since this is for school, i'm sure you can't go crazy with more advanced topics. Lets keep it simple with a switch/case.
You can map the letters to their corresponding number first, just use a switch/case to find the correct number depending on the letter.
For example:
String phoneNumber = "1800ab";
for(int x=0; x < phoneNumber.Length; x++)
{
if(Char.IsLetter(phoneNumber[x]))
{
switch(phoneNumber[x].ToString().ToLower())
{
case "a":
case "b":
case "c":
//This is number 2!
break;
}
}
}
String already implements IEnumerable<char> - so no need to "break up" there.
Mapping of something to something (like letter code to matching number) is generally done with map (associative array) types (in C#/.Net it is Dictionary) that provide mapping one value ("key") to corresponding "value" - consider using that.
string letter1 = AskuserforInput("first letter");
string number1 = SwitchMethod(letter1);
string letter2 = AskuserforInput("second letter");
string number2 = SwitchMethod(letter2);
string letter3 = AskuserforInput("third letter");
string number3 = SwitchMethod(letter3);
string letter4 = AskuserforInput("fouth letter");
string number4 = SwitchMethod(letter4);
string letter5 = AskuserforInput("fifth letter");
string number5 = SwitchMethod(letter5);
string letter6 = AskuserforInput("sixth letter");
string number6 = SwitchMethod(letter6);
string letter7 = AskuserforInput("seventh letter");
string number7 = SwitchMethod(letter7);
string letter8 = AskuserforInput("eigth letter");
string number8 = SwitchMethod(letter8);
string letter9 = AskuserforInput("ninth letter");
string number9 = SwitchMethod(letter9);
string letter10 = AskuserforInput("tenth letter");
string number10 = SwitchMethod(letter10);
//declaring strings
Console.WriteLine("This is the original letter phone digits");
Console.WriteLine("({0}{1}{2})) {3}{4}{5} - {6}{7}{8}{9} ", letter1,letter2, letter3, letter4, letter5, letter6, letter7, letter8, letter9, letter10);//continue this
Console.WriteLine("The actual numbers" );
Console.WriteLine("({0}{1}{2})) {3}{4}{5} - {6}{7}{8}{9} ", number1, number2, number3, number4, number5, number6, number7, number8, number9, number10);//continue this
Console.Read();
#region End Program
//wait for program to acknowledge results
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("\n\nPlease hit ENTER to end program. . .");
Console.Read();
#endregion
Console.Read();
//also pulled this back up from a previous program
}
public static string SwitchMethod(string x)
{
string y = "*";
switch (x)
{
case "0":
y = "0";
break;
case "1":
y = "1";
break;
case "A":
case "a":
case "B":
case "b":
case "C":
case "c":
case "2":
y = "2";
break;
case "D":
case "d":
case "E":
case "e":
case "F":
case "f":
case "3":
y = "3";
break;
case "G":
case "g":
case "H":
case "h":
case "I":
case "i":
case "4":
y = "4";
break;
case "J":
case "j":
case "K":
case "k":
case "L":
case "l":
case "5":
y = "5";
break;
case "M":
case "m":
case "N":
case "n":
case "O":
case "o":
case "6":
y = "6";
break;
case "P":
case "p":
case "Q":
case "q":
case "R":
case "r":
case "S":
case "s":
case "7":
y = "7";
break;
case "T":
case "t":
case "U":
case "u":
case "V":
case "v":
case "8":
y = "8";
break;
case "W":
case "w":
case "X":
case "x":
case "Y":
case "y":
case "Z":
case "z":
case "9":
y ="9";
break;
default:
Console.WriteLine("knucklehead, not a letter");
Console.WriteLine("an '*' will show up");
break;
//used cases, next will use to.lower
//Lynch helped
}
return y;
}
public static string AskuserforInput(string x)
{
Console.WriteLine("\nPlease type {0}", x);
String input = Console.ReadLine();
return input;
}
I'm sure someone can think of a better way, but you could loop through each digit and pass it to this function:
int Asc(char ch)
{
//Return the character value of the given character
return (int)Encoding.ASCII.GetBytes(ch)[0];
}
Then just assign a number based on which ASCII character is returned.

C# switch case how to calculate

Hey I´am trying to add two numbers together via switch case.
I have 3 inputs, number 1 and number 2. The 3rd input is the method which I´d like to calculate number 1 and 2 with(e.g +, -, *, /, etc...)
Now the problem is how do I create something like "this" ? I´ve tried this way, but it does not work...
Is it possible to make switch case like this : case %: ???
Thanks
string firstNumber;
string secondNumber;
string method;
//get numbers
Console.WriteLine ("Get first number");
firstNumber = Console.ReadLine ();
Console.WriteLine ("get 2nd number");
secondNumber = Console.ReadLine ();
Console.WriteLine ("the method to calculate with");
Console.WriteLine (" 1:\"*\"");
Console.WriteLine (" 2:\"/\"");
Console.WriteLine (" 3:\"+\"");
Console.WriteLine (" 4:\"-\"");
method = Console.ReadLine ();
//convert
int methodNew = Convert.ToInt32 (method);
int firstNumberNew = Convert.ToInt32 (firstNumber);
int secondNumberNew = Convert.ToInt32 (secondNumber);
switch (methodNew) {
case 1:
firstNumberNew *= secondNumberNew;
break;
default:
Console.WriteLine ("check the methods.");
break;
}
Console.WriteLine (methodNew);
Of course, you can read in a char and do a switch-case
for it:
int c = Console.Read(); // read from console
switch(c) {
case '/':
// work
break;
case '%':
// work
break;
case '*':
// work
break;
case '+':
// work
break;
}
First get the operator then use switch like this:
char method = Console.ReadKey().KeyChar;
double result = 0.0;
switch (method)
{
case '+':
result = firstNumberNew + secondNumberNew;
break;
case '-':
result = firstNumberNew - secondNumberNew;
break;
case '/':
result = firstNumberNew / secondNumberNew;
break;
case '%':
result = firstNumberNew % secondNumberNew;
break;
default:
Console.WriteLine("Invalid value, try again");
break;
}
Console.WriteLine(result);
It would be better if you change the type of firstNumberNew and secondNumberNew to double.Alşo you can use a while loop to force user to enter a valid character.

Best approach to get ipv4 last octet

I know substring can handle this but, is there a better way to get last octet from an IP ?
Ex.:
192.168.1.100
I want 100
Tks
just for fun:
Console.WriteLine(IPAddress.Parse("192.168.1.33").GetAddressBytes()[3]);
Just for fun I wrote the version which would have the least overhead (string manipulation etc.). #rushui has the correct answer though.
static void Main(string[] args)
{
Console.WriteLine(OctetInIP("10.1.1.100", 0));
Console.ReadLine();
}
static byte OctetInIP(string ip, int octet)
{
var octCount = 0;
var result = 0;
// Loop through each character.
for (var i = 0; i < ip.Length; i++)
{
var c = ip[i];
// If we hit a full stop.
if (c == '.')
{
// Return the value if we are on the correct octet.
if (octCount == octet)
return (byte)result;
octCount++;
}
else if (octCount == octet)
{
// Convert the current octet to a number.
result *= 10;
switch (c)
{
case '0': break;
case '1': result += 1; break;
case '2': result += 2; break;
case '3': result += 3; break;
case '4': result += 4; break;
case '5': result += 5; break;
case '6': result += 6; break;
case '7': result += 7; break;
case '8': result += 8; break;
case '9': result += 9; break;
default:
throw new FormatException();
}
if (result > 255)
throw new FormatException();
}
}
if (octCount != octet)
throw new FormatException();
return (byte)result;
}
It may be overkill, but a simple regex would also do the trick:
(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})
Remember what an IP address is, it is a 32-bit (4 byte) number. So masking the address with the subnet mask would actually be the correct way to do it. If you always want a subnet mask of 255.255.255.0, as your question implies, you can & the number with 0xFF to get the number.
But, if you don't care about efficiency, and only have the address as a string, the split on "." is just fine... :)

Categories

Resources