String Concatenation using '+' operator - c#

Looking at the string class metadata, I only see the operators == and != overloaded. So how is it able to perform concatenation for the '+' operator?
Edit:
Some interesting notes from Eric Lippert on string concatenation:
Part 1
Part 2
There is also a super article from Joel referred in part 2 (http://www.joelonsoftware.com/articles/fog0000000319.html)

It doesn't - the C# compiler does :)
So this code:
string x = "hello";
string y = "there";
string z = "chaps";
string all = x + y + z;
actually gets compiled as:
string x = "hello";
string y = "there";
string z = "chaps";
string all = string.Concat(x, y, z);
(Gah - intervening edit removed other bits accidentally.)
The benefit of the C# compiler noticing that there are multiple string concatenations here is that you don't end up creating an intermediate string of x + y which then needs to be copied again as part of the concatenation of (x + y) and z. Instead, we get it all done in one go.
EDIT: Note that the compiler can't do anything if you concatenate in a loop. For example, this code:
string x = "";
foreach (string y in strings)
{
x += y;
}
just ends up as equivalent to:
string x = "";
foreach (string y in strings)
{
x = string.Concat(x, y);
}
... so this does generate a lot of garbage, and it's why you should use a StringBuilder for such cases. I have an article going into more details about the two which will hopefully answer further questions.

Related

How to format numbers in scientific notation with powers in superscript

I need to write values like:
9.6 x 10²
9.6 x 10¹²
I need to know if there is a way to format numbers as above in a string.
You have to find the appropriate character from the code page you are using, for example UTF-8:
string superScript2 = "²";
There is no such thing as formatting in a string, it is just all data.
Try this:
public static string Eng(this double x, string format="g")
{
const string sup_signs = "⁺⁻⁼⁽⁾ⁿ";
const string sup_digits = "⁰¹²³⁴⁵⁶⁷⁸⁹";
if(double.IsNaN(x) || double.IsInfinity(x))
{
return x.ToString();
}
int num_sign = Math.Sign(x);
x = Math.Abs(x);
// group exponents in multiples of 3 (thousands)
int exp = (int)Math.Floor(Math.Log(x, 10)/3)*3;
// otherwise use:
// int exp = (int)Math.Floor(Math.Log(x, 10));
// and handle the exp==1 case separetly to avoid 10¹
x*= Math.Pow(10, -exp);
int exp_sign = Math.Sign(exp);
exp = Math.Abs(exp);
// Build the exponent string 'dig' from right to left
string dig = string.Empty;
while(exp>0)
{
int n = exp%10;
dig = sup_digits[n] + dig;
exp = exp/10;
}
// if has exponent and its negative prepend the superscript minus sign
if(dig.Length>0 && exp_sign<0)
{
dig = sup_signs[1] + dig;
}
// prepend answer with minus if number is negative
string sig = num_sign<0 ? "-" : "";
if(dig.Length>0)
{
// has exponent
return $"{sig}{x.ToString(format)}×10{dig}";
}
else
{
// no exponent
return $"{sig}{x.ToString(format)}";
}
}
As a test case run
static void Main(string[] args)
{
// Type code here.
double x = Math.PI/50e5;
for(int i = 0; i < 20; i++)
{
// Format output to 12 wide column, right aligned
Debug.WriteLine($"{ Eng(x, "g4"),12}");
x*=50;
}
}
with the output:
628.3×10⁻⁹
31.42×10⁻⁶
1.571×10⁻³
78.54×10⁻³
3.927
196.3
9.817×10³
490.9×10³
24.54×10⁶
1.227×10⁹
61.36×10⁹
3.068×10¹²
153.4×10¹²
7.67×10¹⁵
383.5×10¹⁵
19.17×10¹⁸
958.7×10¹⁸
47.94×10²¹
2.397×10²⁴
119.8×10²⁴
By no means optimized, but it does the job. The exponents are in engineering form (multiples of 3 only, in order to avoid things like 10¹). As a bonus, the number can be formatted to a specific number of significant digits by supplying a format code like g4 or g5 for 4 or 5 digits respectively.
It can handle negative or positive numbers
It can handle negative or positive exponents of 10
In can format the mantissa
It can handle NAN or Inf.
It's in extension form for re-usability
As a follow up to my comment above - does something like this do what you require :
public String FormatAs10Power(decimal val)
{
string SuperscriptDigits = "\u2070\u00b9\u00b2\u00b3\u2074\u2075\u2076\u2077\u2078\u2079";
string expstr = String.Format("{0:0.#E0}", val);
var numparts = expstr.Split('E');
char[] powerchars = numparts[1].ToArray();
for (int i = 0; i < powerchars.Length; i++)
{
powerchars[i] = (powerchars[i] == '-') ? '\u207b' : SuperscriptDigits[powerchars[i] - '0'];
}
numparts[1] = new String(powerchars);
return String.Join(" x 10",numparts);
}
See : https://dotnetfiddle.net/dX7LAF
As per my comment above - the number is first converted to an exponential format string (https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#EFormatString), that string is then split on the exponential separator 'E'. The first array is the numeric part, the second the power of 10 to which it is raised - this is converted to superscript characters using one of the techniques of the link I gave (Convert a string/integer to superscript in C#), converted back to a string & the two parts combined using "x 10" as the new separator.
I have assumed you want the value to single digit precision as per your example with no preceding + sign. If you need anything else you could pass the format as a parameter. The code for superscript + is '\u207A'. There is a link here (at the time of writing) giving the list of superscript codes : http://unicode.org/charts/PDF/U2070.pdf

Fast and low-memory-consumption way to read in pair of numbers from file and process them?

Okay, so this is my challenge taken from CodeEval. I have to read numbers from a file that is formatted in a standard way, it has a pair of numbers separated by a comma on each line (x, n). I have to read in the pair values and process them, then print out the smallest multiple of n which is greater than or equal to x, where n is a power of 2.
EXACT REQUIREMENT: Given numbers x and n, where n is a power of 2, print out the smallest multiple of n which is greater than or equal to x. Do not use division or modulo operator.
I have come up with a number of solutions, but none of them satisfy the computer's conditions to let me pass the challenge. I only get a partial completion with scores that vary from 30 to 80 (from 100).
I'm assuming that my solutions do not pass the speed but more likely the memory-usage requirements.
I would greatly appreciate it if anyone can enlighten me and offer some better, more efficient solutions.
Here are two of my solutions:
var filePath = #"C:\Users\myfile.txt";
int x;
int n;
using (var reader = new StreamReader(filePath))
{
string numsFile = string.Empty;
while ((numsFile = reader.ReadLine()) != null)
{
var nums = numsFile.Split(',').ToArray();
x = int.Parse(nums[0]);
n = int.Parse(nums[1]);
Console.WriteLine(DangleNumbers(x, n));
}
}
<<<>>>
var fileNums = File.ReadAllLines(filePath);
foreach (var line in fileNums)
{
var nums = line.Split(',').ToArray();
x = int.Parse(nums[0]);
n = int.Parse(nums[1]);
Console.WriteLine(DangleNumbers(x, n));
}
Method to check numbers
public static int DangleNumbers(int x, int n)
{
int m = 2;
while ((n * m) < x)
{
m += 2;
}
return m * n;
}
I'm fairly new to C# and programming but these two ways I found to get the best score from several others I have tried. I'm thinking that it's not too optimal for a new string to be created on each iteration, nor do I know how to use a StringBuilder and get the values into an Int from it.
Any pointers in the right direction would be appreciated as I would really like to get this challenge passed.
The smallest multiple of n that is larger or equal to x is likely this:
if(x <= n)
{
return n;
}
else
{
return x % n == 0 ? x : (x/n + 1) * n;
}
As x and n are integers, the result of x/n will be truncated (or effectively rounded down). So the next integer larger than x that is a multiple of n is (x/n + 1) * n
Since you missed the requirements, the modulo version was the most obvious choice. Though you still got your method wrong. m = 2 would not result in the smallest being returned but it could actually be the double of the smallest if n is already larger than x.
x = 7, n = 8 would get you 16 instead of 8.
Also adding 2 to m would result in a similar problem.
x = 5, n = 2 would get you 8 instead of 6.
use the following method instead:
public static int DangleNumbers(int x, int n)
{
int result = n;
while(result < x)
result += n;
return result;
}
Still capable of begin optimized but at least right according to the (now) stated constraints.
I have tried to improve the solution with some suggestions from you guys and take the variables outside the loop and drop the ToArray() call which was redundant.
static void Main(string[] args)
{
var filePath = #"C:\Users\sorin\Desktop\sorvas.txt";
int x;
int n;
string[] nums;
using (var reader = new StreamReader(filePath))
{
string numsFile = string.Empty;
while ((numsFile = reader.ReadLine()) != null)
{
nums = numsFile.Split(',');
x = int.Parse(nums[0]);
n = int.Parse(nums[1]);
Console.WriteLine(DangleNumbers(x, n));
}
}
}
public static int DangleNumbers(int x, int n)
{
int m = 2;
while ((n * m) < x)
{
m += 2;
}
return m * n;
}
So it looks like this. The thing is that even if now the numbers have slightly improved, I got a lower score.
May it be their system to blame ?
Using the first option of reading line by line (rather than reading all lines) is clearly going to use less memory (except potentially in the case where the file is very small (eg "1,1") in which case the overhead of the reader may cause problems but at that point the memory used is probably irrelevant.
Likewise declaring the variables outside the loop is generally better but in this case since the objects are value types I'm not sure it makes a difference.
Lastly the most efficient way of doing your DangleNumbers method is probably using bitwise logic operators and the fact that n is always a power of 2. Here is my attempt:
public static int DangleNumbers3(int x, int n)
{
return ((x-1) & ~(n-1))+n;
}
Essentially it relies on the fact that in binary a power of n is always a 1 followed by zero or more zeros. Thus a multiple of n will always end in that same number of zeros. So if n has M zeros after the one then you can take the binary form of x and if it already ends in M zeros then you have your answer. Otherwise you zero out the last M digits at which point you have the multiple of n that is just under x and then you add 1.
In the code ~(n-1) is a bitmask that has M zeros at the end and the leading digits are all 1. Thus when you AND it with a number it will zero out the trailing digits. I apply this to (x-1) to avoid having to do the check for if it is already the answer and have special cases.
It is important to note that this only works because of the special form of n as a power of 2. This method avoids the need for any loops and thus should run much faster (it has five operations total and no branching at all compared to other looping methods which will tend to have at the very least an operation and a comparison per loop.

Create a numeric value from text

I have searched allot on google without any results I am looking for
I would like to get a numeric value from any string in C#
Ex.
var myString = "Oompa Loompa";
var numericoutput = convertStringToNumericValue(myString);
output/value of numericoutput is something like 612734818
so when I put in another string let say "C4rd1ff InTernaT!onal is # gr3at place#"
the int output will be something like 73572753.
The Values must stay constant, for example so if I enter the same text again of "Oompa Loompa" then I get 612734818 again.
I thought maybe in the way of using Font Family to get the char index of each character, but I don't know where to start with this.
The reason for this is so that I can use this number to generate an index out of a string with other data in it, and with the same input string, get that same index again to recall the final output string for validation.
Any help or point in the right direction would be greatly appreciated
Thanks to Tim I ended up doing the following:
var InputString = "My Test String ~!##$%^&*()_+{}:<>?|";
byte[] asciiBytes = Encoding.ASCII.GetBytes(InputString);
int Multiplier = 1;
int sum = 0;
foreach (byte b in asciiBytes)
{
sum += ((int)b) * Multiplier;
Multiplier++;
}
Obviously this will not work for 1000's of characters, but it is good enough for short words or sentences
int.MaxValue = 2 147 483 647
As an alternative to converting the string to it's bytes, and if a hash won't meet the requirements, here are a couple of shorter ways to accomplish getting a numeric value for a string:
string inputString = "My Test String ~!##$%^&*()_+{}:<>?|"
int multiplier = 0;
int sum = 0;
foreach (char c in inputString)
{
sum += ((int)c) * ++multiplier;
}
The above code outputs 46026, as expected. The only difference is it loops through the characters in the string and gets their ASCII value, and uses the prefix ++ operator (Note that multiplier is set to 0 in this case - which is also the default for int).
Taking a cue from Damith's comment above, you could do the same with LINQ. Simply replace the foreach above with:
sum = inputString.Sum(c => c * ++multiplier);
Finally, if you think you'll need a number larger than Int32.MaxValue, you can use an Int64 (long), like this:
string inputString = "My Test String ~!##$%^&*()_+{}:<>?|"
int multiplier = 0;
long largeSum = 0;
foreach (char c in inputString)
{
largeSum += ((int)c) * ++multiplier;
}

Converting string to function

I want to build in my application the possibility of drawing mathematical functions. In the plotting library that I'm using (OxyPlot) there is a great support for that. See this example:
y = ax³ + bx² + cx + d = 0
is being plotted this way:
new FunctionSeries( x => a*x*x*x + b*x*x + c*x + d, /* other stuff, spacing, number of points, etc */ )
Trigonometrical functions are done the same way:
y = sin(3x) + 5cos(x)
is
new FunctionSeries(x => Math.Sin(3*x) + 5*Math.Cos(x) , ....);
I would be very happy if someone could guide me in the conversion between a string (written in a textbox for example) and a call of a method that has inside the syntax shown.
EDIT: the first parameter in the FunctionSeries(a, ....) a is Func<double, double>
EDIT2: Is there a way to say to the compiler, hey, believe me "x => 5*x*x" is a Func, take it literally
something like :
Func<double, double> f = (Func<double, double>)myString;
Here I have a partial solution:
var expresionData = new List<DataPoint>();
Regex pattern = new Regex("[x]");
for (int i = 0; i < 100; i++)
{
string a = pattern.Replace(ExpresionString, i.ToString());
NCalc.Expression exp = new NCalc.Expression(a);
expresionData.Add(new DataPoint(i,Double.Parse(exp.Evaluate().ToString())));
}
I'm doing a little trick here: I transform each 'x' in the typed string to i, then I evaluate the expression and add the point. It's pretty slow. I'm still very interested in the original question:
How to transform a string to Func<double, double> (or just make the compiler take it literally).

How to parse the following string

I am trying to generate a formula which could be anything like this, this is just a sample,
A + B + C > D - A
Now, A, B, C, D, etc are Column Names of a sheet (like excel sheet) i will be accessing in memory.
I need to generate a Rule, like the above A + B + C > D - A which will decide what kind of values user can add in a Cell.
Currently this is how i have begun:
string toValidate = "A + B + C > D + E - A";
string lhs = "", rhs = "";
string[] comparisonOperators = new string[] { "=", ">", "<", "<>", "!=" };
char[] arithmeticOperators = { '+', '-', '/', '*' };
toValidate = toValidate.Replace(#" ", "");
for (int i = 0; i < comparisonOperators.Length; i++)
{
if (toValidate.Contains(comparisonOperators[i]))
{
operatorIndex = toValidate.IndexOf(comparisonOperators[i]);
break;
}
}
lhs = toValidate.Substring(0, operatorIndex);
rhs = toValidate.Substring(operatorIndex + 1);
string[] columnLhsList = lhs.Split(arithmeticOperators);
string[] columnRhsList = rhs.Split(arithmeticOperators);
However even though i have the strings as lhs and rhs and even my operator which > in the above code, i am not able to understand how can i apply the formula on the sheet itself. I just need to know which Column has which operator associated.
Since i have the individual column names, but not the operator before them, for e.g,
+ before A - before A in another case.
How do i parse the above please help.
It is, however, a very fun question if you want to make simple formula parsers like this yourself.
I advice you to check out this article, since it is very clearly written and understandable because of it.
Shunting-yard Algorithm
Personally, I would never try/dare to create my own formula expression parser. Instead, I would (and did) use one of the may available ones, e.g. NCalc over at CodePlex.com.
Using these tools, it is as easy as writing
Expression e = new Expression("2 + 3 * 5");
Debug.Assert(17 == e.Evaluate());
to get your formula evaluated.
Usually such libraries are very solid, well tested and have a rich function set. It would take ages (if ever) to do such a high quality library on my own.
To further cite the NCalc website, you can even use variables like e.g.:
Expression e = new Expression("Round(Pow([Pi], 2) + Pow([Pi2], 2) + [X], 2)");
e.Parameters["Pi2"] = new Expression("Pi * [Pi]");
e.Parameters["X"] = 10;
e.EvaluateParameter +=
delegate(string name, ParameterArgs args)
{
if (name == "Pi")
args.Result = 3.14;
};
Debug.Assert(117.07 == e.Evaluate());

Categories