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.
Related
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.
The problem is that I have two lists of strings. One list is an approximation of the other list, and I need some way of measuring the accuracy of the approximation.
As a makeshift way of scoring the approximation, I have bucketed each list(the approximation and the answer) into 3 partitions (high, medium low) after sorting based on a numeric value that corresponds to the string. I then compare all of the elements in the approximation to see if the string exists in the same partition of the correct list.
I sum the number of correctly classified strings and divide it by the total number of strings. I understand that this is a very crude way of measuring the accuracy of the estimate, and was hoping that better alternatives were available. This is a very small component of a larger piece of work, and was hoping to not have to reinvent the wheel.
EDIT:
I think I wasn't clear enough. I don't need the two lists to be exactly equal, I need some sort of measure that shows the lists are similar. For example, The High-Medium-Low (H-M-L) approach we have taken shows that the estimated list is sufficiently similar. The downside of this approach is that if the estimated list has an item at the bottom of the "High" bracket, and in the actual list, the item is at the top of the medium set, the score algorithm fails to deliver.
It could potentially be that in addition to the H-M-L approach, the bottom 20% of each partition is compared to the top 20% of the next partition or something along those lines.
Thanks all for your help!!
So, we're taking a sequence of items and grouping it into partitions with three categories, high, medium, and low. Let's first make an object to represent those three partitions:
public class Partitions<T>
{
public IEnumerable<T> High { get; set; }
public IEnumerable<T> Medium { get; set; }
public IEnumerable<T> Low { get; set; }
}
Next to make an estimate we want to take two of these objects, one for the actual and one for the estimate. For each priority level we want to see how many of the items are in both collections; this is an "Intersection"; we want to sum up the counts of the intersection of each set.
Then just divide that count by the total:
public static double EstimateAccuracy<T>(Partitions<T> actual
, Partitions<T> estimate)
{
int correctlyCategorized =
actual.High.Intersect(estimate.High).Count() +
actual.Medium.Intersect(estimate.Medium).Count() +
actual.Low.Intersect(estimate.Low).Count();
double total = actual.High.Count()+
actual.Medium.Count()+
actual.Low.Count();
return correctlyCategorized / total;
}
Of course, if we generalize this to not 3 priorities, but rather a sequence of sequences, in which each sequence corresponds to some bucket (i.e. there are N buckets, not just 3) the code actually gets easier:
public static double EstimateAccuracy<T>(
IEnumerable<IEnumerable<T>> actual
, IEnumerable<IEnumerable<T>> estimate)
{
var query = actual.Zip(estimate, (a, b) => new
{
valid = a.Intersect(b).Count(),
total = a.Count()
}).ToList();
return query.Sum(pair => pair.valid) /
(double)query.Sum(pair => pair.total);
}
Nice question. Well, I think you could use the following method to compare your lists:
public double DetermineAccuracyPercentage(int numberOfEqualElements, int yourListsLength)
{
return ((double)numberOfEqualElements / (double)yourListsLength) * 100.0;
}
The number returned should determine how much equality exists between your two lists.
If numberOfEqualElements = yourLists.Length (Count) so they are absolutely equal.
The accuracy of the approximation = (numberOfEqualElements / yourLists.Length)
1 = completely equal , 0 = absolutely different, and the values between 0 and 1 determine the level of equality. In my sample a percentage.
If you compare these 2 lists, you will retrieve a 75% of equality, the same that 3 of 4 equal elements (3/4).
IList<string> list1 = new List<string>();
IList<string> list2 = new List<string>();
list1.Add("Dog");
list1.Add("Cat");
list1.Add("Fish");
list1.Add("Bird");
list2.Add("Dog");
list2.Add("Cat");
list2.Add("Fish");
list2.Add("Frog");
int resultOfComparing = list1.Intersect(list2).Count();
double accuracyPercentage = DetermineAccuracyPercentage(resultOfComparing, list1.Count);
I hope it helps.
I would take both List<String>s and combine each element into a IEnumerable<Boolean>:
public IEnumerable<Boolean> Combine<Ta, Tb>(List<Ta> seqA, List<Tb> seqB)
{
if (seqA.Count != seqB.Count)
throw new ArgumentException("Lists must be the same size...");
for (int i = 0; i < seqA.Count; i++)
yield return seqA[i].Equals(seqB[i]));
}
And then use Aggregate() to verify which strings match and keep a running total:
var result = Combine(a, b).Aggregate(0, (acc, t)=> t ? acc + 1 : acc) / a.Count;
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();
Been reading about out/ref and tuple, but for the life of me cannot figure out how to implement a way to return three (3) values (whether within same method that calculates my main value, or with separate methods). I am able to perform a calculation with one value (the main value) which deals with pricing for a service.
Here is a snippet of what I've done to calculate that main value:
public class Calculations
{
public decimal decFinancialAccount(QuoteData quoteData)
{
if (quoteData.StepAssetInformation.FinancialAccountDropDown
== StepAssetInformation.FinancialAccount.None)
return 0;
else if (quoteData.StepAssetInformation.FinancialAccountDropDown
== StepAssetInformation.FinancialAccount.One)
return PriceQuote.priceFinancialAccount;
else if (quoteData.StepAssetInformation.FinancialAccountDropDown
== StepAssetInformation.FinancialAccount.Two)
return (PriceQuote.priceFinancialAccount * 2);
...
else
return 0;
}
public decimal CalculateChapter7(QuoteData quoteData)
{
decimal total = PriceQuote.priceChapter7;
...
total += this.decFinancialAccount(quoteData);
return total;
}
}
The above works out great. It obviously has other decimal's that are added, but you get the idea.
Now, I am wanting to perform additional calculations on the CalculateChapter7 value that is returned.
The first value is a DiscountChapter7 / discount (variable in method?) price: above a certain amount, discounts are applied for every increment of 50. I got no problem listing them all out if I have to (rather than complicating things for myself). There is no set formula for the discounts, I just created an Excel sheet to visualize my discounts (see below).
The second value is a CompareChapter7 / compare (variable in method?) price: for every discounted price I offer, a comparison is made to what other's charge for the same service. Again, there is no formula per se, I just used an Excel sheet to figure those out arbitrarily.
In addition, I'd like to (within the "discount" and "compare") do a simple subtraction to show "savings" (calculated price - discounted price = savings) and "difference" (other attorneys charge - discounted price = difference). I imagine when I get the two values above working that these additional two would be simple.
Here is my Excel sheet (just a small snippet):
A few notes about that:
Between 799 and 999 there are no discounts (the "rounded" column is just to bring those numbers to a 50 increment for my ease of use and are not relevant).
The Excel formulas are pretty straightforward (fee - discounted price = savings; other attorneys charge - discounted price = difference) - which is what I am trying to attain within my code.
Can anyone provide a solid example of how to integrate the "discount" and "comparison" with my calculated price?
Thanks!
I didn't really follow your specific scenario but... if you are trying to return 3 things from a function, you're doing it wrong and your code will be a pain to maintain. Just define a new class that has 3 properties and return an instance of this class.
You need to create a new class that will contain all the return values. If it's not going to be used anywhere else, you could nest the class inside the Calculations class as follows, but that's up to you:
public class Calculations
{
public class Result
{
public decimal Total { get; set; }
public decimal Discount { get; set; }
public decimal Comparison {get; set; }
}
public Result CalculateChapter7(QuoteData quoteData)
{
Result result = new Result();
result.Total = ...;
result.Discount = ...;
result.Comparison = ...;
return result;
}
}
When you do it this way, all three return values are packaged up into a single object which is then returned. Each time you call the method, it creates a new Result object and populates it with all the values for that invocation of the method. So, to read the returned values after calling the method, you would need to read each property out of the returned object. For instance you could do something like this:
Calculations calc = new Calculations();
Calculations.Result result = calc.CalculateChapter7(...);
string output = string.Format("Total = {0}, Discount = {1}, Comparison = {2}", result.Total.ToString(), result.Discount.ToString(), result.Comparison.ToString());
I'm gathering light statistics of EXIF data for a large collection of photos and I'm trying to find the simplest way (i.e. performance doesn't matter) of translating Exposure Time values to/from usable data. There is (as far as I can find) no standard for what values camera manufacturers might use i.e. I can't just scan the web for random images and hard-code a map.
Here are is a sample set of values I've encountered (" indicates seconds):
279", 30", 5", 3.2", 1.6", 1.3", 1", 1/1.3, 1/1.6, 1/2, 1/2.5, 1/3, 1/4, 1/5, 1/8, 1/13, 1/8000, 1/16000
Also take into consideration that I'd also like to find the average (mean) ... but it should be one of the actual shutter speeds collected and not just some arbitrary number.
EDIT:
By usable data I mean some sort of creative? numbering system that I can convert to/from for performing calculations. I thought about just multiplying everything by 1,000,000 except some fractions when divided are quite exotic.
EDIT #2:
To clarify, I'm using ExposureTime instead of ShutterSpeed because it contains photographer friendly values e.g. 1/50. ShutterSpeed is more of an approximation (which varies between camera manufacturers) and leads to values such as 1/49.
You want to parse them into some kind of time-duration object.
A simple way, looking at that data, would be to check wheter " or / occurs, if " parse as seconds, / parse as fraction of seconds. I don't really understand what else you could mean. For an example you'd need to specify a language--also, there might be a parser out there already.
Shutter speed is encoded in the EXIF metadata as an SRATIONAL, 32-bits for the numerator and 32-bits for the denominator. Sample code that retrieves it, using System.Drawing:
var bmp = new Bitmap(#"c:\temp\canon-ixus.jpg");
if (bmp.PropertyIdList.Contains(37377)) {
byte[] spencoded = bmp.GetPropertyItem(37377).Value;
int numerator = BitConverter.ToInt32(spencoded, 0);
int denominator = BitConverter.ToInt32(spencoded, 4);
Console.WriteLine("Shutter speed = {0}/{1}", numerator, denominator);
}
Output: Shutter speed = 553859/65536, sample image retrieved here.
It seems there are three types of string you will encounter:
String with double quotes " for seconds
String with leading 1/
String with no special characters
I propose you simply test for these conditions and parse the value accordingly using floats:
string[] InputSpeeds = new[] { "279\"", "30\"", "5\"", "3.2\"", "1.6\"", "1.3\"", "1\"", "1/1.3", "1/1.6", "1/2", "1/2.5", "1/3", "1/4", "1/5", "1/8", "1/13", "1/8000", "1/16000" };
List<float> OutputSpeeds = new List<float>();
foreach (string s in InputSpeeds)
{
float ConvertedSpeed;
if (s.Contains("\""))
{
float.TryParse(s.Replace("\"", String.Empty), out ConvertedSpeed);
OutputSpeeds.Add(ConvertedSpeed);
}
else if (s.Contains("1/"))
{
float.TryParse(s.Remove(0, 2), out ConvertedSpeed);
if (ConvertedSpeed == 0)
{
OutputSpeeds.Add(0F);
}
else
{
OutputSpeeds.Add(1 / ConvertedSpeed);
}
}
else
{
float.TryParse(s, out ConvertedSpeed);
OutputSpeeds.Add(ConvertedSpeed);
}
}
If you want TimeSpans simply change the List<float> to List<TimeSpan> and instead of adding the float to the list, use TimeSpan.FromSeconds(ConvertedSpeed);