ToString() filling Decimal number with zeroes at the right - c#

This is a simple question for sure, but I can't find the solution. It's the opposite of this question. In my case, I have a decimal and a string properties on my ViewModel, like this:
public string FactorText
{
get
{
if (this.Factor != 0)
{
return this.Factor.ToString();
}
}
set
{
this._factorText = value;
}
}
public decimal Factor { get; set; }
When the .ToString() acts, it fills the number with zeroes at the right, e.g:
1.1 becomes 1.100000000000000
1.9999999999 becomes 1.999999999900000
... and so on. It fills the remaing of 15 decimal places with zeroes.
I don't really know why and if it have a way to make sure .ToString() stops making that.
If this information is relevant, that Factor is mapped with Fluent NHibernate as follows:
Map((x) => x.Factor).Column("FACTOR").Precision(30).Scale(15).Not.Nullable();
I don't know if this can be the cause of that behaviour.
Thank you in adv.
Update: I just can't change the scale and precision. They match the column on the database definition that is Decimal(30,15).

It's likely that this is due to how the database is representing the number. For example, if you insert 1.1 in a SQL Server 2008 decimal(30,15) field and select the result, you will get back 1.100000000000000.
See the comments below, the accepted solution was to use .ToString("G29") as found in How to format a decimal without trailing zeros

1.1 becomes 1.100000000000000
^^^^^^^^^^^^^^^ 15 places
The .Scale(15) is what is causing this behavior. Reduce this to the number of decimal places you require.

You can use string.format-Parameters like
string.format("{0:0.0000}",yourvalue");

Just remove Scale(15) to let the original value be loaded.

Maybe this works for you:
if (this.Factor.Length < 15) for (int i = this.Factor.Length; i <= 15; i++) this.Factor += "0";
Regards.,
k
EDIT: Sorry, try this:
return Convert.ToDecimal(this.Factor, CultureInfo.InvariantCulture).ToString();

Related

Replacing float with int - how do I do localized input/output?

This is one of those cases where I assume the solution is on google, but I have no idea what the search term even is. Or even which Tags to use on Stack Overflow.
Situation:
Floats are not precise. A common trick around it, is to use Integers for the math, then shift the decimal point during output:
If you need 4 decimal places of precision for € (not uncommon in finances), you effectively measure and calculate in milli-Euro. Then during output you shift the decimal left, and cut off the last 2 digits:
So a int 1234567 that is stored, retrieved and processes as a int, would print as/stand for "123.45 €" to the normal end user.
Problem:
But how would this interact with localisation? .NET has this awesome part where Parse() and ToString() look at the current Windows Users Culture setting, to figure out what the decimal separator, group separator and group size is today.
There seems to be no fixed point type in .NET, to do the work for me.
Is there some format string combination I could use to say "shift decimal point 4 left into the number, omit last 2 digits)"? F2 would only add two empty 0 past the decimal point for any int. and "1234567.00 €" is a few orders of magnitude off from "123.45 €"
My best idea thus far:
Building my own format string out of the NumberDecimalSeparator, NumberGroupSeparator and NumberGroupSizes from the users culture - but that is just ugly and seems like something I should not be doing. Is there a better day to do it, or is it one of those cases where I have to go for the ugly thing that works?
Maybe something like this
using System.Globalization;
int n = 123456;
string price = "";
string priceW = "";
int i = 0;
foreach(char c in n.ToString())
{
i++;
if(i == n.ToString().Length - 1)
price += ".";
price += c;
}
float rPrice = float.Parse(price, CultureInfo.InvariantCulture.NumberFormat);
priceW = price + "€";

Unity formatting multiple numbers

So I'm a complete newb to unity and c# and I'm trying to make my first mobile incremental game. I know how to format a variable from (e.g.) 1000 >>> 1k however I have several variables that can go up to decillion+ so I imagine having to check every variable's value seperately up to decillion+ will be quite inefficient. Being a newb I'm not sure how to go about it, maybe a for loop or something?
EDIT: I'm checking if x is greater than a certain value. For example if it's greater than 1,000, display 1k. If it's greater than 1,000,000, display 1m...etc etc
This is my current code for checking if x is greater than 1000 however I don't think copy pasting this against other values would be very efficient;
if (totalCash > 1000)
{
totalCashk = totalCash / 1000;
totalCashTxt.text = "$" + totalCashk.ToString("F1") + "k";
}
So, I agree that copying code is not efficient. That's why people invented functions!
How about simply wrapping your formatting into function, eg. named prettyCurrency?
So you can simply write:
totalCashTxt.text = prettyCurrency(totalCashk);
Also, instead of writing ton of ifs you can handle this case with logarithm with base of 10 to determine number of digits. Example in pure C# below:
using System.IO;
using System;
class Program
{
// Very simple example, gonna throw exception for numbers bigger than 10^12
static readonly string[] suffixes = {"", "k", "M", "G"};
static string prettyCurrency(long cash, string prefix="$")
{
int k;
if(cash == 0)
k = 0; // log10 of 0 is not valid
else
k = (int)(Math.Log10(cash) / 3); // get number of digits and divide by 3
var dividor = Math.Pow(10,k*3); // actual number we print
var text = prefix + (cash/dividor).ToString("F1") + suffixes[k];
return text;
}
static void Main()
{
Console.WriteLine(prettyCurrency(0));
Console.WriteLine(prettyCurrency(333));
Console.WriteLine(prettyCurrency(3145));
Console.WriteLine(prettyCurrency(314512455));
Console.WriteLine(prettyCurrency(31451242545));
}
}
OUTPUT:
$0.0
$333.0
$3.1k
$314.5M
$31.5G
Also, you might think about introducing a new type, which implements this function as its ToString() overload.
EDIT:
I forgot about 0 in input, now it is fixed. And indeed, as #Draco18s said in his comment nor int nor long will handle really big numbers, so you can either use external library like BigInteger or switch to double which will lose his precision when numbers becomes bigger and bigger. (e.g. 1000000000000000.0 + 1 might be equal to 1000000000000000.0). If you choose the latter you should change my function to handle numbers in range (0.0,1.0), for which log10 is negative.

How can I force a number to have 3 digits while keeping ALL decimal places?

In c#, I want to force 0s when converting from double to string in case a number is lower than 100, the only challenge is that I want to keep all decimal places. Examples
58.3434454545 = 058.3434454545
8.343 = 008.343
I tried with ToString + a format provider but I'm not certain what's the correct provider for keeping all decimal places
You can use formatter strings for .ToString(), documented here.
To do what you want you can use this as example, noting the maximum digits for double is 17:
double numberA = 58.3434454545;
numberA.ToString("000.##############"); //058.3434454545
double numberB = 8.343;
numberB.ToString("000.##############"); //008.343
This is a rather ass ugly solution but if you wanted the number of decimals to be dynamic you could try something like this:
private string FormatDouble(double dbl)
{
int count = BitConverter.GetBytes(decimal.GetBits((decimal)dbl)[3])[2];
var fmt = string.Concat("000.", new string('#', count));
return dbl.ToString(fmt);
}
Call it like this:
Console.WriteLine(FormatDouble(58.3434454545123123));
Console.WriteLine(FormatDouble(8.3431312323));
And your output would be this:
058.3434454545123
008.3431312323
I'm sure there is a much better way to do this and I'm not sure about performance, but hey it works and you don't have to guess the number of decimals you need, so that's a plus

Is output of Extension Method IEnumerable.Average() wrong for some values?

I have a follows code that i have run on LinqPad:
void Main()
{
List<VariableData> outputVariableData =
new List<VariableData>();
for(int i = 1 ; i< 100; i ++)
{
outputVariableData.Add(new VariableData
{
Id = i,
VariableValue = .33
});
}
double result = outputVariableData.Average(dd=> dd.VariableValue);
double add = outputVariableData.Sum(dd=> dd.VariableValue)/99;
add.Dump();
result.Dump();
}
public class VariableData
{
public int Id { get; set; }
public double VariableValue{ get; set; }
}
It results
0.329999999999999
0.329999999999999
When i check the average of same numbers in the excel sheet with formula =AVERAGE(A1:A101) and it return .33 as it is.
Actually i am drawing chart with this data and average value is showin on the chart, which making the chart drawing so absert and chart is not able to manage such type of value.
I am little confused about the output of these both, i suppose excel automatic round the value. so i have simple and little silly question that is output of my extension method is correct??
As noted, excel gives you a nice rounded version. For displaying of numbers this may be a very useful read: http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx
There is also http://msdn.microsoft.com/en-us/library/f5898377 available.
What's the relevance of Standard Numeric Format Strings You Literally Ask?
Easy - the problem isn't that the numbers wrong - it's perfectly fine given the inaccuracies of floating point numbers. However displaying these numbers can be an issue - it's not what we expect nor is it useful. However, if we spend a few seconds defining how we want our numbers presented...
void Main()
{
List<VariableData> outputVariableData =
new List<VariableData>();
for(int i = 1 ; i< 100; i ++)
{
outputVariableData.Add(new VariableData
{
Id = i,
VariableValue = .33
});
}
double result = outputVariableData.Average(dd=> dd.VariableValue);
double add = outputVariableData.Sum(dd=> dd.VariableValue)/99;
add.Dump();
add.ToString("P0").Dump();
add.ToString("N2").Dump();
result.Dump();
result.ToString("P0").Dump();
result.ToString("N2").Dump();
}
public class VariableData
{
public int Id { get; set; }
public double VariableValue{ get; set; }
}
Suddenly we get the output we want:
0.329999999999999
33 %
0.33
0.329999999999999
33 %
0.33
The problem now isn't trying to massage the numbers to perfection, or using unusual datatype - but spending a few minutes figuring out what options are available and making use of them! It's easy to do and very useful in the long run :)
Of course, this should only be used for displaying data - if you need to round data for computational reasons then I suggest looking into Math.Round etc.
Hope this answers your Q.
Supplemental:
This is another option that works in a very similar vein: http://msdn.microsoft.com/en-us/library/0c899ak8.aspx It explains how to do things like:
void Main()
{
0.31929.ToString("0.##%").Dump();
0.ToString("0.##%").Dump();
1.ToString("0.##%").Dump();
}
Which results in:
31.93%
0%
100%
The computer stores floating point numbers in binary format and there is no exact representation of 0.33
Decimal Binary
2 10
0.5 0.1
0.25 0.01
0.33 0.01010100011110101110000101000111101011100001010001111010111000...
http://www.exploringbinary.com/binary-converter/
It is exactly how computer can present computations from Math point the numbers 0.33 and 0.32(9) are equal, Excel perhaps has own rounding
http://www.cut-the-knot.org/arithmetic/999999.shtml
Floating points will give you rounding differences. It happens.
If you want the numbers to be exact, try using decimal instead of double for VariableValue.
This gives 0.33 for both add and result.

C#, DETERMINE *if* a double can become an int without any loss [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to determine if a decimal/double is an integer?
I have a unique situation in which all numbers must be saved as double data type in my database, but only in certain conditions is the precision beyond the integer level valuable.
At first, I tried to just use int and then abstract to a new table when these unique fractional occurances would happen, but after doing that for weeks I can see now that it is excessively stupid and wasting my time.
I know that I can turn a double into an int. That is easy. I know how to translate it over. What I do not know is how to TEST for translating it over. I basically wish to come up with a short, easy way to say
Is this number really a double, or is it just an int?
If it is an int (and most of the time, it will be), then I will turn it into one and treat it as such. But due to the uniqueness of the requirements, I have to still save everything in the database as double.
Any ideas? I know this is a newbie question, and I've googled around for several hours and am still left quite confused.
Cast it to an int and see if it's still equal:
if ((int)val == val)
(int)val will truncate any fractional portion.
Note that this may behave unexpectedly if the number is too large to retain complete precision in the double.
double d = ...;
if(d == (int)d)
//is int
else
//is not int
Of course due to some precision issues, this may not work 100% times. You can use
double d = ...;
if(Math.Abs(d - (int)d) < Epsilon) //const double Epsilon = 0.000001;
//is int
else
//is not int
This similar post shows you how to determine if a double or decimal has decimal places or not. You can use this to determine what type it is and then store appropriately.
Accepted answer from that post:
For floating point numbers, n % 1 == 0 is typically the way to check if there is anything past the decimal point.
public static void Main (string[] args)
{
decimal d = 3.1M;
Console.WriteLine((d % 1) == 0);
d = 3.0M;
Console.WriteLine((d % 1) == 0);
}
Output:
False
True
try this
double x = ......
if (Math.truncate(x) == x)
....... (is integer, unless its so big its outside the bounds)

Categories