I feel like this is a very noob question.. but I just can't get the right statement for it.
For display purposes, I want to split a double in two: the part before the dot and the first two digits after the dot. I need it as a string. Target language: C#.
E.g.: 2345.1234 becomes "2345" and "12"
I know how to get the part before the dot, that's simply:
Math.Floor(value).ToString()
...but what is the right way to get the part "behind the dot"?
There must be some nice way to do that in a simple way...
I can't think of anything else then:
Math.Round(100 * (value - Math.Floor(value))).ToString("00");
I'm sure there is a better way, but I just can't think of it. Anyone?
Regular expressions (regex) is probably you best bet, but using the mod operator may be another valuable solution...
stuffToTheRight = value % 1
Cheers.
//
//Use the Fixed point formatting option. You might have a bit more work to do
//if you need to handle cases where "dot" is not the decimal separator.
//
string s = value.ToString("F2", CultureInfo.InvariantCulture);
var values = s.Split(".");
string v1 = values[0];
string v2 = values[1];
See this link for more about formatting: http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx
Here is some untested code that tries to take current culture into account:
//
//Use the Fixed point formatting option.
//
string s = value.ToString("F2", CultureInfo.CurrentCulture);
var values = s.Split(CultureInfo.NumberFormat.NumberDecimalSeparator);
string v1 = values[0];
string v2 = values[1];
use regex ".[0-9][0-9]"
In one line it will be:
string[] vals = value.ToString("f2").Split(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.ToCharArray());
vals[0] : before point.
vals[1] : after point.
Related
I am working with doubles. In the Netherlands we make use of 51,3 instead of 51.3. I did write a piece of code that works with dots instead of commas. But the result of the previously written code returns a double the English way, with a dot. I am encountering some strange errors.
Here is what I have:
var calResult = 15.2d;
var calResultString = calResult.ToString(CultureInfo.GetCultureInfo("nl-NL"));
var result = double.Parse(calResultString);
calResult == "15.2" -> as expected
calResultString == "15,2" -> as expected
result == "152" -> here I expect a comma.
A also did try to add the cultureinfo also in the double.Parse. This resulted in a "15.2".
TLDR: I need to convert an English/American double to a Dutch(or similar rules) one.
Thanks in advance! :)
P.S
I hope this is not a duplicate question, but didn't found anything this specific.
You, probably, should either provide "nl-NL" whenever you work with Netherlands' culture
var calResult = 15.2d;
var calResultString = calResult.ToString(CultureInfo.GetCultureInfo("nl-NL"));
// We should parse with "nl-NL", not with CurrentCulture which seems to be "en-US"
var result = double.Parse(calResultString, CultureInfo.GetCultureInfo("nl-NL"));
Or specify CurrentCulture (default culture)
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("nl-NL");
var calResult = 15.2d;
// now CultureInfo.GetCultureInfo("nl-NL") is redundant
var calResultString = calResult.ToString();
var result = double.Parse(calResultString);
Finally, if you have a string which represents some floating point value in en-US culture, and you want the same value but be a string in nl-NL format:
string source = "123.456";
string result = double
.Parse(source, CultureInfo.GetCultureInfo("en-US"))
.ToString(CultureInfo.GetCultureInfo("nl-NL"));
Numbers and strings don't contain any culture information, instead you specify the culture when you convert between numbers and strings.
result == "152" -> here I expect a comma
What happened is that you asked the operating system to parse "15,2" into a double, and didn't specify a culture. It defaulted to US culture and ignored the comma.
If you'd specified a culture:
var result = double.Parse(calResultString, CultureInfo.GetCultureInfo("nl-NL"));
it would have given you the right value (15.2), and that might even have been displayed as 15,2 if your computer was configured to the right number format (and the debugger used your preference).
Ideally you don't hard-code the culture, but use the culture that the user has chosen.
I've written a simple method that will check for the coma character in your input and replace it with a dot. I believe the best way is to take an input as a string value. this way you can manipulate it and then you can parse it and return a double or a string if you wish:
var input = Console.ReadLine();
double parsedDouble;
if (input.Contains(","))
{
input = input.ToString().Replace(",", ".");
}
if (!Double.TryParse(input, out parsedDouble))
{
Console.WriteLine("Error parsing input");
}
else
{
Console.WriteLine(parsedDouble);
}
Console.ReadLine();
edit: the answers from Robin Bennett/Dmitry Bychenko are much better than mine, as mine is just more manual. I wasn't aware of the overload of parse that he had provided.
I'll leave my solution, cause it does solve this issue, even if it's a bit more... brute ;)
var calResult = 15.2d;
var calResultString = calResult.ToString();
string result = double.Parse(calResultString).ToString(CultureInfo.GetCultureInfo("nl-NL"));
I am not sure how this is able to be parsed correctly in C# but I would like it to fail where the case where the comma is not separated every repeatable three value. Example: 1,123.23 should pass but 11,23.23 should fail in my sense. But the actual output is that tryparse seems to always return true regardless of where the position of comma is before decimal.
Edit: Answer with regex is being accepted since it is found that this is a bug. Thank you.
string price = "1,1,2,3.23";
decimal outputValue = 0;
var allowedStyles = (NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands);
if (Decimal.TryParse(price, allowedStyles, CultureInfo.GetCultureInfo("EN-us"), out outputValue))
{
Console.WriteLine("Pass");
}
As you noted NumberStyles.AllowThousands doesn't enforce the comma to be on the correct place. So I think a regular expression can help you here:
Regex.IsMatch("11,23.23", "^[+-]?[0-9]{1,3}(,[0-9]{3})*(.[0-9]*)?$");
I don't know if this helps but, yeah I think I should try. I think my answer is a little but straight forward, just if the concern is the format, I made it compare on a .ToString("format specified"); and compare it to your "price" string. Just my 2 cents.
string price = "1,1,2,3.23";
decimal priceParse = 0;
if (decimal.TryParse(price, out priceParse))
{
string shouldBeFormat = Convert.ToDecimal(priceParse).ToString("#,##0.00");
if (price == shouldBeFormat)
{
// your good
}
else
{
// no good
}
}
You have two acceptable formats, so you can check if the number is parseable and, if so, check it is in an acceptable format:
string price = "1,123.23";
decimal outputValue = 0;
var allowedStyles = (NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands);
var cul = CultureInfo.GetCultureInfo("EN-us");
if (decimal.TryParse(price, allowedStyles, cul, out outputValue))
{
if (outputValue.ToString("N", cul) == price || outputValue.ToString("G", cul) == price)
{
Console.WriteLine("Pass");
}
}
What you discovered is clearly a bug. I strongly recommend do not stuck here, instead implement a workaround. (and also apply KISS).
Unless this code part executed zillion ad zillion times in a high math algorithm's core or any other way is performance critical, here is a simple workaround.
(Supposing the strings are using ',' (comma) as thousand separator. (and they are not decimal separator as it could be some culture)):
price = price.Replace(",",""); // This will not change the value when comma is thousand separator.
// Go forward to parsing
I ran a few different codes and i realized when you apply AllowThousands, the only constraint on the place of ',' is that it should be on the integer part of the number.
some results:
"123,,3.12" => pass
"123,,3.1,3" => fail
Hello everyone as the title say I want to trim the "0." after I do modulo 1 on a double variable
Example:
double Number;
Number = Convert.ToDouble(Console.ReadLine()); //12.777
test = Number % 1; //0.777
I want my output to be: 777
only using math with no
string trims and so...
Thank you all !!
and in c# please
That is just a formatting on the ToString. Take a look at all your options here
How about
.ToString(".###");
Without using any string functions!
while(Math.Round(Number-(int)Number,1)!=1)
{
Number=Number/0.1;
if(Number-(int)Number==0)break;//To cover edge case like 0.1 or 0.9
}
NOTE: Number should be of double type!
If I take your question literally, then you do not want the decimal point either, so .ToString(".###") will not get you what you want, unless you remove the first character (which is string manipulation, and you said you don't want that either).
If you want 777 in a numeric variable (not a string), then you can multiply your result by 1000, though I don't know if you'll always have exactly 3 digits after the decimal or not.
The easiest way really is just to use string manipulation. ToString the result without any formatting, then get the substring starting after the decimal. For example:
var x = (.777d).ToString();
var result = x.SubString(x.IndexOf('.') + 1);
You are certainly looking for this:-
.ToString(".###");
As correctly pointed by Marc in comments you should have everything to be in a string, because if you output that 0.777 as it really is stored internally, you'd get 8 random bytes.
Something like this:-
var num = (.777d).ToString();
var result = num.SubString(num.IndexOf('.') + 1);
The most generic way to do this would be:
using System.Globalization;
var provider = NumberFormatInfo.InvariantInfo;
var output = test.ToString(".###", provider)
.Replace(provider.NumberDecimalSeparator, String.Empty);
You can also set the NumberDecimalSeparator on a custom NumberFormatInfo, but if you set it to empty it will throw the exception "Decimal separator cannot be the empty string."
I currently output a currency value left-aligned, using the following:
String.Format(CultureInfo.CurrentCulture, "{0:#,##0}", value);
I wish to modify the string formatter so that I can right align this. Im not sure how to do it without affecting my existing formatter.
Could someone please advise?
EDIT: I Know it involves something similar to:
http://www.csharp-examples.net/align-string-with-spaces/
String.Format("{0,20:#,##0}", value); will do it.
Example.
not very clear what you actually mean, but I suppose, you are talking about
String.PadLeft method.
Example: to "align" right, you can:
string hello ="hello";
int supportedSymbCount = 10;
int padcount = supportedSymbCount - hello.Length;
if(padCount>0)
hello = hello.PadLeft(padCount);
This will add "pads" in front of the string as much as need to compose a string as long as 10 characters. Choose parameters more sutable to you, and it should work in your case.
For console output use the tab character as a separator,
Console.WriteLine( "\t{0:#,##0}", value )
For web use div class="numeric" with text-align="right".
For other outputs there are no generic solutions.
Use PadLeft or PadRight
int iTotalLength = 20; // Total length of string
char cPadChar = '0'; // Padding character
String.Format(CultureInfo.CurrentCulture, "{0:#,##0}", value).PadLeft(iTotalLength,
cPadChar);
I am working on a C# application. I want to change number decimal figure with comma(,) where i have dot(.) using regular expression.
For example:
Price= 100,00.56
As this international rule of representing numeric values but I Sweden they have different ways for numbers Like
Price= 100.00,56
So i want to change dot(.) into comma(,) and comma(,) into dot(.) using RegEx. Could guide me about this.
When formatting numbers, you should use the string format overload that takes a CultureInfo object. The culture name for swedish is "sv-SE", as can be seen here.
decimal value = -16325.62m;
Console.WriteLine(value.ToString(CultureInfo.CreateSpecificCulture("sv-SE")));
Edit:
As #OregonGhost points out - parsing out numbers should also be done with CultureInfo.
Not a RegEx solution but from my experience - more correct:
public static string CheckDecimalDigitsDelimiter(this string instance)
{
var sv = new CultureInfo("sv-SE");
var en = new CultureInfo("en-US");
decimal d;
return (!Decimal.TryParse(instance, NumberStyles.Currency, sv, out d) &&
Decimal.TryParse(instance, NumberStyles.Currency, en, out d)) ?
d.ToString(sv) : // didn't passed by SV but did by EN
instance;
}
What does this method do? It ensures that if given string is incorrect Sweden string but is correct English - convert it to Sweden, e.g. 100,00 -> 100,00 but 100.00 -> 100,00.
You can do this even without regex. For example
var temp = price.Replace(".", "<TEMP>");
var temp2 = temp.Replace(",", ".");
var replaced = temp2.Replace("<TEMP>", ",");
Also have a look at
System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator
Not sure what 100,00.56 represents, did you mean 10.000,56?
To answer your question:
For such a simple task, why use RegEx? You can do it much easier:
string oldValue = "100,00.56";
char dummyChar = '&'; //here put a char that you know won't appear in the strings
var newValue = oldValue.Replace('.', dummyChar)
.Replace(',', '.')
.Replace(dummyChar, ',');
Edit
I agree with #Oded, for formatting numbers use the CultureInfo class.
Do not rely on RegExp for this kind of thing :) Use the build in cultures fx:
decimal s = decimal.Parse("10,000.56", NumberStyles.Currency, CultureInfo.GetCultureInfo("en-US"));
string output = s.ToString("N",CultureInfo.GetCultureInfo("da-DK"));
en-US will parse it correctly and da-DK uses the other kind of representation. I live in DK and therefore use that but you should use the culture which fits your output.