0

My question is similar to this one:

Leave only two decimal places after the dot

However there is an added complexity. The numerical value is suffixed with a unit that can change into anything i.e.

string test = "0.1542 Mol";

or

string test1 = "0.5247 ml";

Essentially, I'd like something that can deal with both situations that can do this:

string test = "0.15 Mol";

and

string test1 = "0.52 ml";
bobsyauncle
  • 152
  • 8
  • 1
    you should seperate **data** from **representation**. Having said this you want to round your **data** up to 2 decimales. Afterwards you can turn that into a string by appending some spaces, units or whatever. Btw: are you aware that in the post you refer to there´s also a unit included which turns your question in an exact duplicate? – MakePeaceGreatAgain May 24 '20 at 11:05

5 Answers5

2

You need to split the string then round the value. String.Format ($) will also do that in a single step:

string test = "0.1542 Mol";
string[] testParts = test.Split(' ');
string rounded = $"{Convert.ToDecimal(testParts[0]):0.00} {testParts[1]}";

Fiddle: https://dotnetfiddle.net/EQsJGf

jscarle
  • 1,045
  • 9
  • 17
  • Same approach as my answer with few lines, why not take it all the way to one: `string rounded = $"{Convert.ToDecimal(test.Split(' ')[0]):0.00} {test.Split(' ')[1]}";` – George Kerwood May 24 '20 at 11:17
  • To be honest, I'm always at a toss up when it comes to code efficiency regarding String.Split. I know we're only talking about a few nanoseconds and a few bytes of memory, but I never really figured out what is more efficient on an internal level (processor and memory wise). Split a string and store its values, or repeatedly split a string without using storage variables. – jscarle May 24 '20 at 11:24
  • Would be interesting to know :) – George Kerwood May 24 '20 at 11:26
  • What if you didn't want rounding to take place? Converting to decimal will round it automatically – bobsyauncle May 24 '20 at 11:31
  • Also I've not seen $ get used much. What does that do? – bobsyauncle May 24 '20 at 11:35
  • @bobsyauncle https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated It's a nice little "shortcut" for `String.Format()` – George Kerwood May 24 '20 at 11:42
  • 2
    Looks like, for the processor portion at least, my approach of storing the Split is more efficient: https://dotnetfiddle.net/BMr9Xh – jscarle May 24 '20 at 11:47
  • Thanks guys, that `$` is a nice little touch – bobsyauncle May 24 '20 at 11:58
  • 1
    The Stopwatch is a fun little tool. – jscarle May 24 '20 at 12:05
1

UPDATE

You can use Regex:

var s = "0.153567 Mol";
var num = Regex.Replace(s, @"^([0-9]+\.[0-9]{2})([0-9]*)(\s+.+)", "$1$3");
// Output: 0.15 Mol

UPDATE 2

If you need to round a number, you still can use Regex (pattern is changed a bit):

string[] nums = { "0.154567 Mol", "0.158963 ml" };
foreach (var num in nums)
{
    var s = Regex.Replace(num, @"^([0-9]+\.[0-9]+)(\s+.+)",
            m => $"{Math.Round(decimal.Parse(m.Groups[1].Value), 2)}{m.Groups[2].Value}");
    Console.WriteLine(s);
}
// Output:
//   0.15 Mol
//   0.16 ml
Community
  • 1
  • 1
JohnyL
  • 6,894
  • 3
  • 22
  • 41
  • Down wasn´t mine, but I´d stringly discourage from using a regex to manipulate numeric data. – MakePeaceGreatAgain May 24 '20 at 11:12
  • I think you missed the question, OP requested an input of "0.1542 Mol" to an output of "0.15 Mol". (Not the downvoter) – George Kerwood May 24 '20 at 11:12
  • You're essentially doing a Floor, not a Round with Regex. Also your second capturing group is also unnecessary, if you're going to go the Regex route. Without the 2nd capturing group: ^([0-9]+\.[0-9]{2})(?:[0-9]*)(\s+.+) – jscarle May 24 '20 at 11:20
  • 1
    @jscarle Didn't understand you about floor and round. Doesn't OP need just to strip off remained digits after two digits (after comma)? – JohnyL May 24 '20 at 11:54
  • 1
    I wasn't saying it was wrong, it was just an observation. I was stating that using Regex as such is synonymous to a Math.Floor, whilst using a String.Format was synonymous to a Math.Round. The OP didn't state clearly which one he expected. – jscarle May 24 '20 at 11:57
  • I added Regex as a performance comparison just for curiosity: https://dotnetfiddle.net/hptvYU – jscarle May 24 '20 at 12:13
  • @jscarle *she lol ;). Tbf I didn't state whether I wanted it rounded or simply stripped. It's good to have both options. – bobsyauncle May 24 '20 at 17:46
  • 1
    @bobsyauncle Well, it's still possible to round a number with Regex :) – JohnyL May 24 '20 at 17:50
  • 1
    @bobsyauncle I have updated code - you can use Regex to round numbers, too (update 2). – JohnyL May 24 '20 at 19:06
  • 1
    @jscarle Added a version with rounding (update 2). – JohnyL May 24 '20 at 19:07
  • 1
    If we ignore the scenic route for the solution, that's some creative use of Regex for ya. ;) – jscarle May 24 '20 at 20:48
0

You need to first convert your string to a double that you can round, then reformat to text with the addition of your original units:

    string inputText = "0.1542 Mol";
    double inputNumber = Convert.ToDouble(inputText.Split(' ')[0]);
    double outputNumber = Math.Round(inputNumber, 2);
    string outputText = outputNumber + " " + inputText.Split(' ')[1];
George Kerwood
  • 1,248
  • 8
  • 19
0
var splittedString = variable.Split(" ");
var number = String.Format("{0:0.00}", splittedString[0]); 
var result = number + " " + splittedString[1] ;
Flori Bruci
  • 436
  • 4
  • 11
0

I'm not a C# person, but since no one else has answered this for you, I'll try to help, given my experience with other languages. I would suggest the following solution:

Treat the string as a delimited string with the space as the delimiter. Search for the position of the space, copy the left portion to one variable and the right version to another variable. The IndexOf() and subString() methods in C# might be useful here. Then convert the left side variable to a numeric value and convert it back to string with the appropriate precision. Combine that with the right side string and you'll have what you want.

Here's a link to another thread about ways to get the precision that you are desiring:

Formatting a float to 2 decimal places