Representing double values in the exponential format in C# - c#

Need to display the values in the floating point format as well as in exponential format
if the value is greater or equal to 0.01 and less than or equal to 1000
display in the expotential format else display in the floating format
For eg : 3.230000000 is displayed as 3.23
0.00001 is displayed as 1E-05
But the problem with my code if number given is 1 then the number is displayed as 1.00.
if (dValue >= 0.01|| dValue <= 1000.0)
return (string.Format("{0:0.##E+00}", dValue));
else
return (string.Format("{0:F2}", dValue));
Please let me know how to check the number does not contain decimal values

Round the number to two decimal places and to an integer, and see if the results are "close enough":
if (dValue >= 0.01 && dValue <= 1000.0)
{
if (Math.Abs(Math.Round(dValue, 2) - Math.Round(dValue, 0)) < 0.005) {
return string.Format("{0:F0}", dValue);
else
return string.Format("{0:F2}", dValue);
}
else return (string.Format("{0:0.##E+00}", dValue));
The thing to note here is that (as always with floating point numbers) the comparison between the two rounded results should not be an equality comparison.

Replace your last line
return (string.Format("{0:F2}", dValue))
to
return (string.Format("{0:0.##}", dValue))

Consider simply using G format.
Or use Math.Truncate to get integral part, that see if it ie the same as original number (need to take into account output format precision to do comparison with desider eps, probably 0.005 in your case).

Too much time. :)
You will get 2 digits maximum with values like 3.234.
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Format(0.00001));
Console.WriteLine(Format(1));
Console.WriteLine(Format(3.2));
Console.WriteLine(Format(3.22));
Console.WriteLine(Format(3.256));
Console.ReadLine();
}
static string Format(double dValue)
{
if (dValue >= 0.01 && dValue <= 1000.0)
{
int temp = (int)Math.Round(dValue * 100);
if (temp % 100 == 0)
return ((int)dValue).ToString();
else if (temp % 10 == 0)
return (string.Format("{0:F1}", dValue));
else
return (string.Format("{0:F2}", dValue));
}
else
return (string.Format("{0:0.##E+00}", dValue));
}
}
gives
1E-05
1
3,2
3,22
3,26
Probably there are cleaner solutions?!

Related

Check if a string is percentage value

I'm trying to write this in C#. The requirement is very straightforward - check if a string input is a value within the range from 0 to 100.
I want to make sure the string is either an integer value in the range of 0 to 100 or
a double that's within the same range as well.
So for example, these are the accepted values:
0
50
100
0.1
50.7
100.0
I checked the double.parse method here but not sure if it's the one I'm looking for: https://learn.microsoft.com/en-us/dotnet/api/system.double.tryparse?view=net-7.0#system-double-tryparse(system-string-system-iformatprovider-system-double#)
The reason is that it can also parse string like this one: 0.64e2 (which is 64)
Is this something that can be achieved with built-in library already?
Wrote you a little snippet:
// C# function to check if string is a percentage between 0 and 100
public static bool IsPercentage(string s)
{
// regex check if s is a string with only numbers or decimal point
if (Regex.IsMatch(s, #"^\d+\.?\d*$"))
{
double d = Convert.ToDouble(s);
return d >= 0 && d <= 100;
}
return false;
}
Also returns false if the string contains % or has exponential (e).
if my understanding of the Q was correct and exponential representations like mentioned "0.64e2" is unwanted:
static bool IsPercentage(string s)
{
if (Single.TryParse(s, NumberStyles.AllowLeadingSign |
NumberStyles.AllowDecimalPoint, NumberFormatInfo.InvariantInfo, out Single n))
return n >= 0 && n <= 100;
return false;
}

Regex to allow numeric values between[1-100] and a percentage symbol

I want a regex to allow numeric values between 1 to 100 and one percentage symbol
Valid samples:
0%,
100%,
100,
0,
65%
Invalid samples: 101, 101%, 100.1, 65.6%, 65.6
Any help is appreciated
i dont speak regex but you saied any help would be appreciated so here i go:
bool Verify(string input)
{
input = input.Replace("%", ""); // if it contains % remove it
int value;
if (Int32.TryParse(input, out value)) //if the input can be converted into a number
{
if (value > 1 && value < 100) //and the value is in range
{
return true; //return true to confirm it
}
}
return false; //in any other case return false
}
Matches a percentage between 0 and 100 (inclusive). Accepts up to 2 decimal places.
ex: 0% , 100% , .17%
^( 100(?:\.0{1,2})? | 0*?\.\d{1,2} | \d{1,2}(?:\.\d{1,2})? )% $
Try this:
^(0*100{1,1}\.?((?<=\.)0*)?%$)|(^0*[1-9]\d{0,1}\.?((?<=\.)\d*)?%)$
It will allow 65% and 100% and discard 65 and 100.1%

Formatting floating point numbers in C#: decimal separator always visible

How do I get 12. from 12 value with standard .NET string formatting? I've tested 0.### and it does not work.
double number = 12;
string.Format("{0:0.###}", number); // returns "12" not "12."
double number = 12.345;
string.Format("{0:0.###}", number); // returns "12.345"
Currently I've resolved with string manipulation but is it somewhat possible with standard string.Format()?
Thanks.
I think you can first check if the double is actually and integer, and if yes, use a simple string.Format("{0}.", number):
double number = 12;
if (number % 1 == 0)
Console.Write(string.Format("{0}.", number));
C# demo
double number = 12;
string.Format((number % 1 == 0) ? "{0}." : "{0}", number);
Gives 12.
double number = 12.345;
string.Format((number % 1 == 0) ? "{0}." : "{0}", number);
Gives 12.345

How to format number into ten thousands [duplicate]

Is there a way using a string formatter to format Thousands, Millions, Billions to 123K, 123M, 123B without having to change code to divide value by Thousand, Million or Billion?
String.Format("{0:????}", LargeNumber)
There are different ways to achieve this, but for me the easiest and quickest is to use the "," custom specifier
double value = 1234567890;
// Displays 1,234,567,890
Console.WriteLine(value.ToString("#,#", CultureInfo.InvariantCulture));
// Displays 1,234,568K
Console.WriteLine(value.ToString("#,##0,K", CultureInfo.InvariantCulture));
// Displays 1,235M
Console.WriteLine(value.ToString("#,##0,,M", CultureInfo.InvariantCulture));
// Displays 1B
Console.WriteLine(value.ToString("#,##0,,,B", CultureInfo.InvariantCulture));
I use this mix of formats in an Extension Method (just add it to your project and enjoy) 😎
public static string ToKMB(this decimal num)
{
if (num > 999999999 || num < -999999999 )
{
return num.ToString("0,,,.###B", CultureInfo.InvariantCulture);
}
else
if (num > 999999 || num < -999999 )
{
return num.ToString("0,,.##M", CultureInfo.InvariantCulture);
}
else
if (num > 999 || num < -999)
{
return num.ToString("0,.#K", CultureInfo.InvariantCulture);
}
else
{
return num.ToString(CultureInfo.InvariantCulture);
}
}
Use:
((decimal)235).ToKMB();
// 235
((decimal)1235).ToKMB();
// 1.2K
((decimal)6271235).ToKMB();
// 6.27M
((decimal)93246571235).ToKMB();
// 93.247B
Notes:
It return more detail for bigger numbers and I like it.
It support negative numbers too. (Thanks to #Dusty for his note in comments.
I write a method for decimal numbers in this example, you can write some override methods for it to support int, long and double to use it without any casting such as:
myIntNumber.ToKMB();
myLongNumber.ToKMB();
myDoubleNumber.ToKMB();
myDecimalNumber.ToKMB();
You can implement a ICustomFormatter that divides the value by thousand, million or billion, and use it like this:
var result = string.Format(new MyCustomFormatter(), "{0:MyFormat}", number);

rounding to the best unit without losing precision

I receive a decimal number with a maximum of 4 digits after the "." and I know this number is in milligram.
I have to find the best matching unit (milligram, gram, kilogram) for the number.
for an example if I receive
edited
116000000.0000 milligram, it's going to return 116.0000 kilogram
66990000.0000 milligram, it's going to return 66.9900 kilogram
49000010.0000 milligram, it's going to return 49000.0100 g
49000000.0100 milligram, it's going to return 49000000.0100 milligram
1001 milligram, it's going to return 1.0010 gram
1010 milligram, it's going to return 1.0100 gram
1000 milligram, it's going to return 0.0010 kilogram
1100 milligram, it's going to return 0.0011 kilogram
135005 milligram, it's going to return 135.0050 gram
and last sample 10013500 milligram, it's going to return 10.0135 kilogram
I'm currently using this code, which I think look/is ugly and can fail
Dim temp As Decimal
Dim u = New List(Of Integer)(New Integer() {1, 1000, 1000000})
For i = 0 To u.Count - 1
temp = CDec(qty / u(i))
If (temp * 10000) - Math.Truncate(temp * 10000) <> 0 AndAlso (temp * 10000) - Math.Truncate(temp * 10000) < 1 Then
temp = CDec(qty / u(i - 1))
Exit For
End If
Next
qty = temp
is there a better/nicer way of doing what I do?
edit for precision
the input can be any decimal between 0.0001 and maximum that a decimal can accept in .net
the output need to be rounded to the best unit with a maximum of 4 digits after "." without losing any precision
Gen the numbers and choose the suitable one.
public static decimal FormatDecimal(decimal i)
{
decimal milli = i;
decimal grams = decimal.Round(i / 1000m, 4);
decimal kilo = decimal.Round(grams / 1000m, 4);
if (kilo * 1000 * 1000 == milli)
{
return kilo;
}
if (grams * 1000 == milli)
{
return grams;
}
return milli;
}
And to test:
public static void FormatDecimalTest()
{
if (FormatDecimal(116000000.0000m) == 116.0000m)
Console.WriteLine("ok1");
if (FormatDecimal(66990000.0000m) == 66.9900m)
Console.WriteLine("ok2");
if (FormatDecimal(49000010.0000m) == 49000.0100m)
Console.WriteLine("ok3");
if (FormatDecimal(49000000.0100m) == 49000000.0100m)
Console.WriteLine("ok4");
if (FormatDecimal(1001m) == 1.0010m)
Console.WriteLine("ok5");
if (FormatDecimal(1000m) == 0.0010m)
Console.WriteLine("ok6");
if (FormatDecimal(1100m) == 0.0011m)
Console.WriteLine("ok7");
if (FormatDecimal(1100m) == 0.0011m)
Console.WriteLine("ok8");
if (FormatDecimal(135005m) == 135.0050m)
Console.WriteLine("ok9");
if (FormatDecimal(10013500m) == 10.0135m)
Console.WriteLine("ok10");
}
In your question, I see you used a loop over the various factors. Here's a looping solution that will find the first factor that does not lose precision.
public static decimal FormatDecimal(decimal i)
{
List<decimal> myFactors = new List<decimal>()
{ 1000m * 1000m, 1000m};
foreach (decimal conversionFactor in myFactors)
{
decimal result = decimal.Round(i / conversionFactor, 4);
if (result * conversionFactor == i)
{
return result;
}
}
return i;
}
Why don't you just use ifs? something like:
if (num > 1000000)
return string.format("{0.####} kg", num/1000000)
if (num > 1000)
return string.format("{0.####} g", num/1000);
return string.format("{0.####} mg", num);
I wouldn't be above doing a CStr on the number, counting the characters, removing all trailing zeros, counting the number again, and deciding on a unit based on the number of characters in your string. Then just divide the original number by the correct magnitude and append the unit.
Before doing that, though, you'd want to do a Truncate on the original and see if the returned value matches the original; then you just use mg.
Probably won't work any better than your code, but it might be easier to read. Maybe.
Your sample doesn't make too much sense, but your should go with something like this:
static string FormatWeight(double value)
{
if (value > 10000000) return (value / 10000000D).ToString("0.#### t");
if (value > 100000) return (value / 100000D).ToString("0.#### kg");
if (value > 1000) return (value / 1000D).ToString("0.#### g");
return value.ToString("0.#### mg");
}
would you not be better either implementing or using a unit library for the conversions, then formatting the results afterwards?
some projects here and here, although I can't vouch for the quality of any of it...
and java one discussed here
so if I understood correctly, any argument ARG which comes with a fraction <> 0 will stay as is and expressed in mg ... this should be easy to code
If ARG <> Int(ARG) Then
' Return ARG
Endif
anything without a fraction should be converted to the most appropriate unit (mg, g, dag, kg, t, etc). So for these we need to to look at the argument as a string and count the "0"es from the back-end and see from there how often we may divide by 10 without loosing numeric precision.
In your first example we count 6 Zeroes from the backend, so we could safely divide by 10^(6+4) to get not more than 4 fractional digits (which is more than we actually need).
In your last example we count 2 "0"es from the back, so we can safely divide by 10^(2+4).
So if the "save division power" is >=6, divide by 10^6 and express in kg
if the "save division power is between 5 and 3, divide by 10^3 and express in g, below 3 leave as mg.
Hope that helps.

Categories