.NET: Shortest possible string representation of a double value - c#

The general ("G") format specifier converts a number to the more compact of either fixed-point or scientific notation. The problem is there still can be leading zeros in exponent.
Example:
Double d = 0.000001;
Console.WriteLine(d.ToString("G"));
1E-06
Is there a numeric format string that will remove leading zero in exponent so the result is
1E-6
I still want the function to return fixed-point notation if it is more compact. In other words, I want the shortest string representation of a double value.
edit: I would like to do it without post-processing

You can use post-processing to remove leading zeros.
static string Compact(double d)
{
var s = d.ToString("G");
if(s.Contains("E-0") || s.Contains("E+0"))
{
s = Regex.Replace(s, #"(\d+)(E[+-])0+(\d+)", "$1$2$3");
}
return s;
}
Usage
Console.WriteLine(Compact(0.000001)); // result: 1E-6
Console.WriteLine(Compact(12342353465345432313123123123.0)); // result: 1.23423534653454E+28
Console.WriteLine(Compact(0.000011)); // result: 1.1E-5

This can be done by using the longhand version of the formatting, and manually selecting the number of digits
Double d = 0.000001;
Console.WriteLine(d.ToString("0.###E-0"));
1E-6
The exact version I have made will round a number like 0.0000012351573 to 1.235E-6
If you really wanted the shortest you could techincally use
Console.WriteLine(d.ToString("0E-0"));
This will round it but always have only one digit- for example
Double d = 0.0000018;
Console.WriteLine(d.ToString("0.###E-0"));
2E-6

Related

How to display trailing zeroes?

How do I keep the trailing zeroes like the example below. When I input -.230 with no leading zeroes it only displays -0.23 without the trailing zero. But when I input -0.230 it yields the expected result which is -0.230.
Actual output: -.230 -> -0.23
Expected output: -.230 -> -0.230
I have also tried String.Format("{0:0.000}", n) but it still does not work.
Looks like you are converting to string so you can use the following
someNumber.ToString("N3");
See the MSDN docs for details on how this works, about halfway down the page it also has examples of a bunch of different codes.
It seems that you are print the same number on which you have performed string.format.
Try to store the output of string.format and use that. I have used the same approach that you have used and got the expected answer. Refer following code
var n = -.23;
string str = string.Format("{0:0.000}", n);
Console.WriteLine(str); // This will give you an expected output
Console.WriteLine(n); // This won't give you an expected output
double and decimal mentioned in the question, are quite different types. double is a binary floating point value and it doesn't keep trailing zeroes:
double value = -0.230;
Console.Write(value); // -0.23
Unlike double, decimal being decimal floating-point does store the trailing zeroes:
decimal value = -0.230m; // note suffix "m"
Console.Write(value); // -0.230
When represented as string values of these types can be formatted, e.g. with F3
format string which stands for "3 digits after the decimal point":
double v1 = -0.230;
decimal v2 = -0.230m;
Console.Write($"{v1:f3} {v2:f3}");
Outcome:
-0.230 -0.230

How to check values numbers after the decimal point [duplicate]

This question already has answers here:
Remove trailing zeros
(23 answers)
Closed 5 years ago.
I have tried looking for a similar question here but I can only find how to count the number of decimal places.
What I want to know is: how do I find the value of the decimal places that are >0?
For example, if we have:
decimal value = 1.920m;
decimal value2 = 1.900m;
How do I check if the values after the decimal point are >0?
I want to be able to check this and restrict the display accordingly so I can display something like this:
1.92
1.9
Essentially you want to display the value with the max number of decimal places available and remove the trailing zeros. This is the easiest way to do it:
Console.WriteLine(value.ToString("G29")); // Output 1.92
Alternate solution (which works for numbers smaller than 0.00001m unlike the above solution). Though this doesn't look as neat as the previous solution using G29, this works better since it also covers numbers smaller than 0.00001:
Console.WriteLine(value.ToString("0.#############################")); // Output 1.92
We are using G29 since 29 is the maximum available digits for a decimal. The G or General Format Specifier is used to define the maximum number of significant digits that can appear in the result string. Any trailing zeros are truncated using this format specifier. You can read more about it here.
Input: 1.900m
Output: 1.9
Input: 14.571428571428571428571428571M
Output: 14.571428571428571428571428571
Input: 0.00001000000m
Output: 1E-05 (Using first solution G29)
Output: 0.00001 (Using second solution)
If i understand you right you can do something like this:
double x = 1.92;
x-=(int)x;
while(x%1>0){
x*=10;
}
Console.WriteLine(x);
output:
92
now you can check what you want on this number
If you want to convert to decimal only use this
static decimal? RemoveTrailingZeros(this decimal? value)
{
if (value == null) return null;
var format = $"0.{string.Join(string.Empty, Enumerable.Repeat("#", 29))}";
var strvalue = value.Value.ToString(format);
return ConvertToDecimalCultureInvariant(strvalue);
}
static decimal? ConvertToDecimalCultureInvariant(this string value)
{
decimal decValue;
if (!decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out decValue))
{
return null;
}
return decValue;
}
Since the precision of a decimal is 29 hence Enumerable.Repeat("#", 29).
And use it as
var result = RemoveTrailingZeros(29.0000m);

How do I trim the "0." after I do modulo 1 on a double variable

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."

String Format for Thousand separators

Is there a way using String Formatter I can achieve the following:
$52,152 to $52.1
I have a series of values that are all thousands and I will like to display them in the above format.
Thanks
This works for $52.2, using the , number scaling specifier:
string.Format("{0:$0,.0}", 52152);
If you really want 52.1, you’ll probably have to do it “manually”; sorry. All custom formatting strings seem to round.
In your case the non-formatted versions of your 2 numbers are inherently different
52152 != 52.1
A better solution might be to send the correct numbers to the UI but if not, you can use the , scaling specifier - http://msdn.microsoft.com/en-us/library/0c899ak8.aspx#SpecifierTh
void Main()
{
decimal x = 52152M;
var a = string.Format("{0:C}", x); //Current Format in Local Culture
Console.WriteLine(a); //Prints €52,152.00
var b = string.Format("${0:00000}", x); //Custom Format, no decimals
Console.WriteLine(b);//Prints $52152
var c = string.Format("${0:###,###,###}", x); //Custom Format, no decimals + 1000 seperators
Console.WriteLine(c);//Prints $52,152
var d = string.Format("${0:###,###,.0}", x); //Custom Format, 1 decimal place, 1000 seperators to support values over 1 million
Console.WriteLine(d);//Prints $52.2
}
Something like this?
string input = "$52,152";
var number = long.Parse(input, NumberStyles.Currency);
string result = (number / 100L / 10m).ToString("C1");
Explanation. First division is an integer division that truncates. Second division is a System.Decimal division.
This assumes a culture (for example new CultureInfo("en-US")) where the currency sign is "$" and the thousands separator is ",".

How can I convert string to decimal with trailing zero(s)

Suppose that we have stringvalue=125.32600 when it convert to decimal value with this code
decimal d;
decimal.tryparse(stringvalue,out d)
d value is 125.326
how can I do this convert with final result 125.32600
You cannot because 125.32600 is equal to 125.326. In this case however I guess that you want to print it out with specific format, which can be done like this:
Console.WriteLine(d.ToString("f5"));
Read Standard Numeric Format Strings
UPDATE
Extension method:
public string Format(this decimal source, int precision)
{
if (precision < 0)
{
throw new ArgumentOutOfRangeException("Precision must be a non negative integer");
}
return source.ToString("f" + precision);
}
which can be used like this:
Console.WriteLine(d.Format(5));
Your code works as written (as long as the decimal separator matches your culture):
decimal d;
decimal.TryParse("125.32600", NumberStyles.Number, CultureInfo.InvariantCulture, out d);
s = d.ToString(CultureInfo.InvariantCulture); // 125.32600
Decimal already remembers how many trailing zeros it has. This is caused by decimal representing numbers in non-normalized form, with an integer mantissa and an exponent representing the number of decimal digits. e.g. 125.32600 is represented as 12532600 * 10^-5
The answer is: You can't, at least not like that.
EDIT: correction: decimal already works like that; but you'll still find below a useful way to store your decimals in a DB.
Why? Because that's not how decimals are stored in memory.
Solution: if you need to keep the trailing zeros, just remember the precision explicitly in a separate field (of a class you should create for this purpose); or store the decimals in string form and only convert to decimal as needed.
string strValue = "125.32600";
int precision = strValue.Length - 1; // only the "12332600" part
decimal value = Decimal.Parse(strValue);
stores 8 in precision and 125.326 in value.
To get back the original form:
int afterPt = precision - ((int) value).ToString().Length;
Console.WriteLine(value.ToString("f" + afterPt));
prints
125.32600
P.S. you have to be aware of floating point binary representation issues though, so stuff like 4.05 might be stored as e.g. 4.049999999999999999, so if you need to guarantee this won't happen, use an algorithm that bypasses decimal altogether and uses only integers for storage and computation.
string strValue = "125.32600";
// parse and store
int value = int.Parse(strValue.Replace(".", ""));
int periodIx = strValue.IndexOf(".");
// get back the original representation
string str = value.ToString();
Console.WriteLine(str.Substring(0, periodIx) + "." + str.Substring(periodIx, str.Length - periodIx));
NOTE: Make sure to use , instead of . in locales that need it.
What you can do is count the zeroes in string and then store them in separate DB field. When you want the result with zeroes just concatenate the same no. of zeroes into decimal number string.
ex.
string p="123.456000";
int zeroes=p.Split('0').Length - 1; // guess
decimal value = Decimal.Parse(p); //without zeroes
string valWithZero=value.toString().padRight(zeroes,'0'); //with zeroes
If you really want to have the zeros in the database you could save it as a string, preformatted, but that would be very inefficient.
What is the problem you try to solve by this, there might be a better solution?

Categories

Resources