I'm converting bytes into gigabytes and when I do, the output is something like:
57.686961286
Is there any way I can cut down the total number displayed to something like:
57.6?
Yes, you could use the Math.Round method, which will round a value to the nearest integer or the specified number of decimal places.
The appropriate overload will be chosen depending on the type of the value that you pass in (either a Double or a Decimal). Specifying an Integer value for the second parameter allows you to indicate the number of fractional digits the result should contain. In this case, you would specify "1".
Of course, the result would not be 57.6. When the value 57.686… is rounded, the 8 in the hundredths place causes the 6 in the tenths place to round up to 7, rather than down to 6. The correct result is 57.7.
Certain overloads of the above method also allow you to specify a rounding style to apply when the number in question is halfway between two others, either IEEE Standard 754 section 4 rounding (also called rounding-to-nearest, or "banker's" rounding), or the "away from zero" style that you probably learned in school.
You can format the value for display using the ToString() method, which takes a format parameter.
double myValue = 57.686961286;
string outputValue = myValue.ToString("0.0"); //output: 57.7, rounded
Related
I try to validate that an input string is a float. To achieve this I pass the input string like "1.000e-45" which is closer to 0 than the c# float minimum allows (1.401298E-45). I expect float.tryParse to return false. Instead it returns true and the parsed number is rounded up to the float minimum (1.401298E-45). If the string contains an even lower number, float.TryParse() seems to round down to 0.
Do I miss something?
What could I do to validate that low numbers like this are not interpreted as float?
var isFloat = float.TryParse("1.000e-45", NumberStyles.Float, CultureInfo.InvariantCulture, out var number);
Update: the user input MUST be a float in a string. it is not allowed to be of higher precision because of a specification. Just imagine it as some kind of API which gives me a string which should be a float value. I have to validate that it is in the ranges of a float.
Update 2: this is not a question about float precision. I know that you cannot have 100% precision because of the binary aspect and the size of the mantisse. As i stated in the question, i know the most close value to 0 for a float. I just didnt expect TryParse() to do rounding like this when its close to 0. I expected it to fail.
Update 3: I hope this makes it more clear. That is the specification that i have to follow.
The input is a string. the string represents a number. like "3.45e12"
the number is not allowed to be outside of the range of "±3.4028235e+38".
the number is not allowed to be smaller in magnitute than "±1.401298e-45". That is what the specification says."0" is allowed too, but not something like "1e-100" or "1e-46".
What i want to do is validate that the user input (a string) fullfills this specification. I dont have to convert the string number into a c# number type and calculate with it. I just have to validate the input string number and then i send the string number to an API. This api would have problems when the string does not match the specification.
I tried to use float.TryParse() for this validation. It works for the min/max ranges (.Net Framework). But it seems to be the wrong approach. float.TryParse() will always return true for number strings that are closer to 0 than it can actually represent and it will round the result to fit into a float: it rounds down to 0 (e.g. for "1e-46") or rounds up to 1.401298E-45 (e.g. for "1e-45". It makes sense to some point, because it does the same when it can not handle the precision of a value like "999999999999999.9" which is not above max and not too close to 0. It rounds it to 1e13.
This question already has answers here:
Formatting doubles for output in C#
(10 answers)
Closed 8 years ago.
Is there a way to get a string showing the exact value of a double, with all the decimal places needed to represent its precise value in base 10?
For example (via Jon Skeet and Tony the Pony), when you type
double d = 0.3;
the actual value of d is exactly
0.299999999999999988897769753748434595763683319091796875
Every binary floating-point value (ignoring things like infinity and NaN) will resolve to a terminating decimal value. So with enough digits of precision in the output (55 in this case), you can always take whatever is in a double and show its exact value in decimal. And being able to show people the exact value would be really useful when there's a need to explain the oddities of floating-point arithmetic. But is there a way to do this in C#?
I've tried all of the standard numeric format strings, both with and without precision specified, and nothing gives the exact value. A few highlights:
d.ToString("n55") outputs 0.3 followed by 54 zeroes -- it does its usual "round to what you probably want to see" and then tacks more zeroes on the end. Same thing if I use a custom format string of 0.00000...
d.ToString("r") gives you a value with enough precision that if you parse it you'll get the same bit pattern you started with -- but in this case it just outputs 0.3. (This would be more useful if I was dealing with the result of a calculation, rather than a constant.)
d.ToString("e55") outputs 2.9999999999999999000000000000000000000000000000000000000e-001 -- some of the precision, but not all of it like I'm looking for.
Is there some format string I missed, or some other library function, or NuGet package or other library, that is able to convert a double to a string with full precision?
You could try using # placeholders if you want to suppress trailing zeroes, and avoid scientific notation. Though you'll need a lot of them for very small numbers, e.g.:
Console.WriteLine(double.Epsilon.ToString("0.########....###"));
I believe you can do this, based on what you want to accomplish with the display:
Consider this:
Double myDouble = 10/3;
myDouble.ToString("G17");
Your output will be:
3.3333333333333335
See this link for why: http://msdn.microsoft.com/en-us/library/kfsatb94(v=vs.110).aspx
By default, the return value only contains 15 digits of precision although a maximum of 17 digits is maintained internally. If the value of this instance has greater than 15 digits, ToString returns PositiveInfinitySymbol or NegativeInfinitySymbol instead of the expected number. If you require more precision, specify format with the "G17" format specification, which always returns 17 digits of precision, or "R", which returns 15 digits if the number can be represented with that precision or 17 digits if the number can only be represented with maximum precision.
You can also do:
myDouble.ToString("n16");
That will discard the 16th and 17th noise digits, and return the following:
3.3333333333333300
If you're looking to display the actual variable value as a number, you'll likely want to use "G17". If you're trying to display a numerical value being used in a calculation with high precision, you'll want to use "n16".
Let's say we have the following simple code
string number = "93389.429999999993";
double numberAsDouble = Convert.ToDouble(number);
Console.WriteLine(numberAsDouble);
after that conversion numberAsDouble variable has the value 93389.43. What can i do to make this variable keep the full number as is without rounding it? I have found that Convert.ToDecimal does not behave the same way but i need to have the value as double.
-------------------small update---------------------
putting a breakpoint in line 2 of the above code shows that the numberAsDouble variable has the rounded value 93389.43 before displayed in the console.
93389.429999999993 cannot be represented exactly as a 64-bit floating point number. A double can only hold 15 or 16 digits, while you have 17 digits. If you need that level of precision use a decimal instead.
(I know you say you need it as a double, but if you could explain why, there may be alternate solutions)
This is expected behavior.
A double can't represent every number exactly. This has nothing to do with the string conversion.
You can check it yourself:
Console.WriteLine(93389.429999999993);
This will print 93389.43.
The following also shows this:
Console.WriteLine(93389.429999999993 == 93389.43);
This prints True.
Keep in mind that there are two conversions going on here. First you're converting the string to a double, and then you're converting that double back into a string to display it.
You also need to consider that a double doesn't have infinite precision; depending on the string, some data may be lost due to the fact that a double doesn't have the capacity to store it.
When converting to a double it's not going to "round" any more than it has to. It will create the double that is closest to the number provided, given the capabilities of a double. When converting that double to a string it's much more likely that some information isn't kept.
See the following (in particular the first part of Michael Borgwardt's answer):
decimal vs double! - Which one should I use and when?
A double will not always keep the precision depending on the number you are trying to convert
If you need to be precise you will need to use decimal
This is a limit on the precision that a double can store. You can see this yourself by trying to convert 3389.429999999993 instead.
The double type has a finite precision of 64 bits, so a rounding error occurs when the real number is stored in the numberAsDouble variable.
A solution that would work for your example is to use the decimal type instead, which has 128 bit precision. However, the same problem arises with a smaller difference.
For arbitrary large numbers, the System.Numerics.BigInteger object from the .NET Framework 4.0 supports arbitrary precision for integers. However you will need a 3rd party library to use arbitrary large real numbers.
You could truncate the decimal places to the amount of digits you need, not exceeding double precision.
For instance, this will truncate to 5 decimal places, getting 93389.42999. Just replace 100000 for the needed value
string number = "93389.429999999993";
decimal numberAsDecimal = Convert.ToDecimal(number);
var numberAsDouble = ((double)((long)(numberAsDecimal * 100000.0m))) / 100000.0;
I need double value to be rounded to 2 digits.
What is preferrable?
String.Format("{0:0.00}", 123.4567); // "123.46"
Math.Round(123.4567, 2) // "123.46"
Math.Round(double,digits) with digits>0 is conceptually very unclean. But I think it should never be used. double is a binary floating point number and thus has no well-defined concept of decimal digits.
I recommend using string.Format, or just ToString("0.00") when you only need to round for decimal display purposes, and decimal.Round if you need to round the actual number(for example using it in further calculations).
Note: With decimal.Round you can specify a MidpointRounding mode. It's common to want AwayFromZero rounding, not ToEven rounding.
With ToEven rounding 0.005m gets rounded to 0.00 and 0.015 gets rounded to 0.02. That's not what most people expect.
Comparisons:
ToEven: 3.75 rounds to 3.8
ToEven: 3.85 rounds to 3.8 (That's not what most people expect)
AwayFromZero: 3.75 rounds to 3.8
AwayFromZero: 3.85 rounds to 3.9
for more information see: https://msdn.microsoft.com/en-us/library/system.math.round.aspx
They are different functions, if you need the output to be displayed, use the first one (that also forces decimals to appear). You will avoid the overhead of the inevitable .ToString() that will occur if the variable is of type double.
Note that the second one rounds the number but if it's an integer result, you will get just the integer (ie: 7 vs 7.00)
That depends on what you want to do with it.
String.Format will return a string, Math.Round(double) will return a double.
the former outputs a string, the latter a double. What's your use of the result ? The answer of this will give the answer of your question.
If you want to return this value as a string then String.Format is better and if you want to return this value as a double in that case Math.Round is better. It totally depends on your requirement.
Math.Round will not add any decimal places if there aren't any to begin with. String.Format will.
e.g.: Math.Round(2) returns 2;
String.Format("{0:0.00}",2) returns 2.00;
How would I round the following number in C# to obtain the following results.
Value : 500.0349999999
After Rounding to 2 digits after decimal : 500.04
I have tried Math.Round(Value,2, MidpointRounding.AwayFromZero); //but it returns the value 500.03 instead of 500.04
You're asking for non-standard rounding rules. The value 500.03499999999 rounded to the nearest hundredth should be 500.03. Since the thousandths digit is less than 5, the hundredths digit remains unchanged.
One way I can see to achieve your desired result is to round the number to the decimal place one smaller than what you ultimately want. Then round that result to the precision you want.
In your example, you would round the value to 3 decimal places resulting in 500.035. You would then round that to 2 decimal places which should result in 500.04 (assuming you're using MidpointRounding.AwayFromZero.
Hope that helps.
You could make it needlessly complex and wrap a variable Round(Decimal, Int32) function in a for loop. Decrement the Int32 to work it's way back to the decimal precision needed. It's a bit of work but like Eric said, you are asking for non-standard rounding rules.
Extra details: http://msdn.microsoft.com/en-us/library/ms131274.aspx