I want to convert string values to decimal. When there is a smaller or greater symbol I want to add/remove to the value like this
string value | decimal result
--------------|----------------
"< 0.22" | 0.219
"< 32.45" | 32.449
"> 2.0" | 2.01
"> 5" | 5.1
This has to work for decimal numbers with any number of decimal places. Is there an elegant way to do this?
I can only think of counting the number of decimal places, getting the last digit, adding/removing ...
So I would imagine the following solution
Split the string on the space
Identify the sign (GT or LT)
Count the number of decimal places and store that value
Convert the number to a decimal
Based on the symbol either add or subtract 10^(-1 * (numberOfDecimals + 1))
Using Regex
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[] inputs = {
"< 0.22",
"< 32.45",
"> 2.0"
};
string pattern = #"(?'sign'[\<\>])\s+(?'integer'\d+).(?'fraction'\d+)";
decimal number = 0;
foreach(string input in inputs)
{
Match match = Regex.Match(input, pattern);
if(match.Groups["sign"].Value == ">")
{
number = decimal.Parse(match.Groups["integer"].Value + "." + match.Groups["fraction"].Value);
number += decimal.Parse("." + new string('0', match.Groups["fraction"].Value.Length) + "1");
}
else
{
number = decimal.Parse(match.Groups["integer"].Value + "." + match.Groups["fraction"].Value);
number -= decimal.Parse("." + new string('0', match.Groups["fraction"].Value.Length) + "1");
}
Console.WriteLine(number.ToString());
}
Console.ReadLine();
}
}
}
Solution without counting the decimals:
If the string starts with >, append "1". If the string starts with < replace the last character by the next lower one (Notice: for "0"->"9" and repeat on the character left to it) and then append "9".
Then split at the blank and Double.Parse the right part.
No need to count digits or split apart the decimal... (you can run this in linqpad)
string inputString = "> 0.22";
string[] data = inputString.Split(' ');
double input = double.Parse(data[1]);
double gt = double.Parse(data[1] + (data[1].Contains('.') ? "1" : ".1"));
switch(data[0])
{
case ">":
gt.Dump(); // return gt;
break;
case "<":
double lt = input - (gt - input);
lt.Dump(); // return lt;
break;
}
// you could even make it smaller by just doing (instead of the switch):
return data[0]==">" ? gt : input - (gt - input);
If trailing zeros are allowed as input but are considered insignificant then trim them.
inputString = inputString.TrimEnd("0");
Related
I'm trying to format a number in a very specific way when displaying it, I've tried messing around with String.Format but couldn't find a way to make this work exactly as I needed.
For example, let's way that I have a variable of type Double with the value "123459.7889" and that I want to format it as "459.788" (000.000) but only during Console.WriteLine() and without rounding or changing the internal value of the number. The full value of the number would not show up and it should technically "overflow" the string because it should only print the first 3 numbers to the left of the decimal point.
Here are some example inputs and example outputs:
12345.678 formatted to "000.000" would become 345.678
1000000.678 formatted to "000.000" would become 000.678
1.777888 formatted to "000.000" would become 001.777
99999.9 formatted to "000.000" would become 999.900
Basically, no matter the internal size of the number, the formatted output should always be the 3 numbers to the left of the decimal point and the 3 numbers to the right of the decimal point with zeros to replace the missing spaces if there's any.
I've tried looking at the examples on the C# documentation and found this:
double value = 123459.7889;
string result = String.Format("{0,8:00000000} {0,8:00000000.000}", value);
Console.WriteLine(result);
But it doesn't work exactly like I needed it to. When running it the numbers are rounded so it becomes 00123459.789 instead of 00123459.788 for example and if the number grows it no longer stays at that fixed size.
try this:
double value = 123459.7889;
Console.WriteLine((Math.Truncate(Math.Abs(value) % 1000) + double.Parse((Math.Round(Math.Abs(value), 3, MidpointRounding.ToZero) -
Math.Truncate(Math.Abs(value))).ToString(".000"))).ToString("000.000"));
value= 123459.7889; result=345.678
value= 1000000.678; result=000.678
value= 1.777888; result=001.777
value= 99999.9; result=999.900
value= 152; result=152 .000
value= -100.02; result=100.020
value= 10.0005; result=010.000
We can use PadLeft and PadRight to fill up zeros when value characters are not enough.
Implementation:
static void Main(string[] args)
{
double value = 1.12;
string valueStr = value.ToString().Replace("-", ""); // convert to string
// check if value does not contain decimal and add
if (!valueStr.ToString().Contains("."))
valueStr += valueStr + ".0"; // add decimal part
var arr = valueStr.ToString().Split(".");
string intValue = arr[0]; //1
intValue = intValue.PadLeft(3,'0'); //001
intValue = intValue.Substring(intValue.Length - 3, 3); //001
string decimalValue = arr[1]; //12
decimalValue = decimalValue.PadRight(3,'0'); //120
decimalValue = decimalValue.Substring(0, 3); //120
string result = $"{intValue}.{decimalValue}";
Console.WriteLine(result);
}
Result:
12345.678 > 345.678
1000000.678 > 000.678
1.777888 > 001.777
99999.9 > 999.900
152 > 152.000
-100.02 > 100.020
-10.0005 > 010.000
You shouldn't need to convert to string, nor should you rely on splitting on a character that may or may not be the decimal character in the language you are running. You can do all the calculations on the numbers and then format the output without allocating any strings except for the result.
public static string FormatNumber(double number)
{
int first = ((int)number)%1000;
int second = (int)Math.Truncate((number-(int)number)*1000)%1000;
return $"{first:000}.{second:000}";
}
static string Format(double number)
{
return string.Format("{0:N3}", number % 1000).PadLeft(7,'0');
}
How it works:
Remove the upper digits using modulus (%)
Format to three decimal places using a format string
Pad left using PadLeft()
Full example:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var tests = new Dictionary<double,string>
{
{ 12345.678D, "345.678" },
{ 1000000.678, "000.678" },
{ 1.777888, "001.778" },
{ 99999.9, "999.900"}
};
foreach (var pair in tests)
{
Console.WriteLine("Expected: {0} Actual: {1}", pair.Value, Format(pair.Key));
}
}
static string Format(double number)
{
return string.Format("{0:N3}", number % 1000).PadLeft(7,'0');
}
}
Output:
Expected: 345.678 Actual: 345.678
Expected: 000.678 Actual: 000.678
Expected: 001.778 Actual: 001.778
Expected: 999.900 Actual: 999.900
Fiddle
try this
int i = value.ToString().IndexOf(".");
string result = string.Concat(value.ToString().Substring(i - 3, 3),".", value.ToString().Substring(i + 1, 3));
Console.WriteLine(result);
I found this question in StackOverFlow but it didn't solve my problem.
How do I format a double to a string and only show decimal digits when necessary?
Weight
0.500
18.000
430.000
by the solution in above url my result show in this form:
Weight
0.5
18
430
and my problem is in decimal digits, I want show decimal digits in 3 digit,like this:
Weight
0.500
18
430
You can use Digit placeholder # with Zero placeholder 0 after dot . in string format.
string num = d % 1 == 0 ? d.ToString(".###") : d.ToString(".000");
Digit placeholder
Replaces the pound sign with the corresponding digit if one is
present; otherwise, no digit appears in the result string.
Zero placeholder
places the zero with the corresponding digit if one is present;
otherwise, zero appears in the result string.
This msdn article Custom Numeric Format Strings explains how the number could be formated.
I think you can't do what you want with single string.Format(). So you can use a clause:
if(weight % 1.0 > 0){
string.Format("{0:0.000}", weight)
}
else {
string.Format("{0:0}", weight)
}
Or even better:
string.Format(weight % 1.0 > 0 ? "{0:0.000}" : "{0:0}", weight)
EDIT: Sorry missed a bit =))
EDIT: If you need to floor result you can use:
string.Format(weight % 1.0 >= 0.001 ? "{0:0.000}" : "{0:0}", weight)
Try
num.ToString("G3") // for 3 significant digits
http://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx
You can use like below method:
Usage:
string format1 = GetFormat(123.4567);
string format2 = GetFormat(123.45);
string format3 = GetFormat(123.0);
//format1 = 123.46
//format2 = 123.45
//format3 = 123
private static string GetFormat(double d)
{
string format;
if (d == Convert.ToInt32(d))
format = string.Format("{0:0.##}", d);
else
format = string.Format("{0:0.00}", d);
return format;
}
For more information:
http://csharpexamples.com/c-string-formatting-for-double/
http://msdn.microsoft.com/en-us/library/vstudio/0c899ak8%28v=vs.100%29.aspx
I found the solution:
string[] strList = Weight.ToString().Split('.');//or ',' for diffrent regions
if(strList[1] == "000")
str = string.Format("{0:#,0.########}", b);
thank you:)
I need to convert any number in a fixed format with a fixed amount of characters. Means 1500 and -1.5 or 0.025 need to have the same length. I also have to give the format in this form: Format = "{???}";
When i type Format = "{0000}"; i can limit 1500 to "1500", but -1.5 -> "-0001.5" means i have too much numbers after the point.
Negative sign place can be done with Format = "{ 0.0;-0.0; 0.0}".
How can i fix the count of the numbers for different numbers?
The length of the string doesn't matter, the most important is the equal length.
Examples:
1500 -> " 1500.000" or " 1500"
-1500 -> "-1500.000" or "- 1500" or " -1500"
1.5 -> " 1.500" or " 1.5"
-0.25-> " -0.250" or "- 0.25"
0.00005 -> " 0.000" or " 0"
150000-> " 150000.0" or " 150000"
15000000 " 15000000"
Edit:
I want to Format an y-Axis of a Chart. I can't use something like value.ToString("???") i need to use chartArea.AxisY.LabelStyle.Format = "{???}";
Why don't use formatting? "F3" forces 3 digits after decimal point and PadLeft ensures the overall length
Double value = 1500.0;
// 3 digits after decimal point, 9 characters length
String result = value.ToString("F3").PadLeft(9, ' ');
0 -> 0.000
1500.0 -> 1500.000
-1500.0 -> -1500.000
-0.25 -> -0.250
Another (similar) possibility is String.Format:
Double value = 1500.0;
// Put value at place {0} with format "F4" aligned to right up to 9 symbols
String result = String.Format("{0:9,F4}", value);
Try it > result = Math.Round(yourValue, 3);
Check full reference here !
you cannot achieve this by a simple format function
string result = string.Empty;
var array = dec.ToString().Split('.');
if (dec > 0)
{
result = array[0].PadLeft(9).Remove(0, 9);
if (array.Count() > 1)
{
result += '.' + array[1].PadRight(3).Remove(3);
}
}
else
{
result = "-"+array[0].PadLeft(9).Remove(0, 9);
if (array.Count() > 1)
{
result += '.' + array[1].PadRight(3).Remove(3);
}
}
Trying to come up with a 'simple' regex to mask bits of text that look like they might contain account numbers.
In plain English:
any word containing a digit (or a train of such words) should be matched
leave the last 4 digits intact
replace all previous part of the matched string with four X's (xxxx)
So far
I'm using the following:
[\-0-9 ]+(?<m1>[\-0-9]{4})
replacing with
xxxx${m1}
But this misses on the last few samples below
sample data:
123456789
a123b456
a1234b5678
a1234 b5678
111 22 3333
this is a a1234 b5678 test string
Actual results
xxxx6789
a123b456
a1234b5678
a1234 b5678
xxxx3333
this is a a1234 b5678 test string
Expected results
xxxx6789
xxxxb456
xxxx5678
xxxx5678
xxxx3333
this is a xxxx5678 test string
Is such an arrangement possible with a regex replace?
I think I"m going to need some greediness and lookahead functionality, but I have zero experience in those areas.
This works for your example:
var result = Regex.Replace(
input,
#"(?<!\b\w*\d\w*)(?<m1>\s?\b\w*\d\w*)+",
m => "xxxx" + m.Value.Substring(Math.Max(0, m.Value.Length - 4)));
If you have a value like 111 2233 33, it will print xxxx3 33. If you want this to be free from spaces, you could turn the lambda into a multi-line statement that removes whitespace from the value.
To explain the regex pattern a bit, it's got a negative lookbehind, so it makes sure that the word behind it does not have a digit in it (with optional word characters around the digit). Then it's got the m1 portion, which looks for words with digits in them. The last four characters of this are grabbed via some C# code after the regex pattern resolves the rest.
I don't think that regex is the best way to solve this problem and that's why I am posting this answer. For so complex situations, building the corresponding regex is too difficult and, what is worse, its clarity and adaptability is much lower than a longer-code approach.
The code below these lines delivers the exact functionality you are after, it is clear enough and can be easily extended.
string input = "this is a a1234 b5678 test string";
string output = "";
string[] temp = input.Trim().Split(' ');
bool previousNum = false;
string tempOutput = "";
foreach (string word in temp)
{
if (word.ToCharArray().Where(x => char.IsDigit(x)).Count() > 0)
{
previousNum = true;
tempOutput = tempOutput + word;
}
else
{
if (previousNum)
{
if (tempOutput.Length >= 4) tempOutput = "xxxx" + tempOutput.Substring(tempOutput.Length - 4, 4);
output = output + " " + tempOutput;
previousNum = false;
}
output = output + " " + word;
}
}
if (previousNum)
{
if (tempOutput.Length >= 4) tempOutput = "xxxx" + tempOutput.Substring(tempOutput.Length - 4, 4);
output = output + " " + tempOutput;
previousNum = false;
}
Have you tried this:
.*(?<m1>[\d]{4})(?<m2>.*)
with replacement
xxxx${m1}${m2}
This produces
xxxx6789
xxxx5678
xxxx5678
xxxx3333
xxxx5678 test string
You are not going to get 'a123b456' to match ... until 'b' becomes a number. ;-)
Here is my really quick attempt:
(\s|^)([a-z]*\d+[a-z,0-9]+\s)+
This will select all of those test cases. Now as for C# code, you'll need to check each match to see if there is a space at the beginning or end of the match sequence (e.g., the last example will have the space before and after selected)
here is the C# code to do the replace:
var redacted = Regex.Replace(record, #"(\s|^)([a-z]*\d+[a-z,0-9]+\s)+",
match => "xxxx" /*new String("x",match.Value.Length - 4)*/ +
match.Value.Substring(Math.Max(0, match.Value.Length - 4)));
How do I format a decimal value to a string with a single digit after the comma/dot and leading spaces for values less than 100?
For example, a decimal value of 12.3456 should be output as " 12.3" with single leading space. 10.011 would be " 10.0". 123.123 is "123.1"
I'm looking for a solution, that works with standard/custom string formatting, i.e.
decimal value = 12.345456;
Console.Write("{0:magic}", value); // 'magic' would be a fancy pattern.
This pattern {0,5:###.0} should work:
string.Format("{0,5:###.0}", 12.3456) //Output " 12.3"
string.Format("{0,5:###.0}", 10.011) //Output " 10.0"
string.Format("{0,5:###.0}", 123.123) //Output "123.1"
string.Format("{0,5:###.0}", 1.123) //Output " 1.1"
string.Format("{0,5:###.0}", 1234.123)//Output "1234.1"
Another one with string interpolation (C# 6+):
double x = 123.456;
$"{x,15:N4}"// left pad with spaces to 15 total, numeric with fixed 4 decimals
Expression returns: " 123.4560"
value.ToString("N1");
Change the number for more decimal places.
EDIT: Missed the padding bit
value.ToString("N1").PadLeft(1);
Many good answers, but this is what I use the most (c# 6+):
Debug.WriteLine($"{height,6:##0.00}");
//if height is 1.23 => " 1.23"
//if height is 0.23 => " 0.23"
//if height is 123.23 => "123.23"
All above solution will do rounding of decimal, just in case somebody is searching for solution without rounding
decimal dValue = Math.Truncate(1.199999 * 100) / 100;
dValue .ToString("0.00");//output 1.99
Note the "." could be a "," depending on Region settings, when using string.Format.
string.Format("{0,5:###.0}", 0.9) // Output " .9"
string.Format("{0,5:##0.0}", 0.9) // Output " 0.9"
I ended up using this:
string String_SetRPM = $"{Values_SetRPM,5:##0}";
// Prints for example " 0", " 3000", and "24000"
string String_Amps = $"{(Values_Amps * 0.1),5:##0.0}";
// Print for example " 2.3"
Thanks a lot!