First question: Can ILNumerics read matfiles with struct? I couldnt make it work.
I then split the file in matlab and I would like to use it for calculations. but i have problems with the subarray function. I would like to do this:
using (ILMatFile matRead = new ILMatFile(#"C:\Temp\Dates.mat"))
{
ILArray<double> Dates = matRead.GetArray<double>("Dates");
double x = 736055-1;
double y = 736237+1;
ILArray<ILLogical> LogDates = (Dates > x && Dates < y);
}
using (ILMatFile matRead = new ILMatFile(#"C:\Temp\Power.mat"))
{
ILArray<double> power = matRead.GetArray<double>("Power");
ILArray<double> tpower = power[LogDates, full];
double avgpower = tpower.Average();
Console.WriteLine(avgpower.ToString());
Console.ReadKey();
}
This doesnt work for a number of reasons. The logical doesnt take my syntax and I dont really get why. But also the subarry in the second block doesnt work, it doesnt know the full keyword (even though the documentation says it shouldand also it doesnt like the logical. obviously I want to average tpower over all columns and only those rows where the logical condition is one.
thanks.
nik
ILLogical is an array itself. You use it like that:
ILLogical LogDates = ILMath.and(Dates > x, Dates < y);
If you still experiencing problems with the subarray, try:
ILArray<double> tpower = power[ILMath.find(LogDates), ILMath.full];
Only, if your class is derived from ILMath, you can ommit the ILMath. identifier! Otherwise, string subarray definitions are sometimes shorter:
ILArray<double> tpower = power[ILMath.find(LogDates), ":"]
In order to take the average over selected rows, reducing to one:
double avgpower = tpower.Average(); // Linq version
double avgpower = (double)ILMath.sumall(tpower) / tpower.S.NumberOfElements; // prob. faster on large data
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.
I have an in memory dataset that I'm trying to get an evenly distributed sample using LINQ. From what I've seen, there isn't anything that does this out of the box, so I'm trying to come up with some kind of composition or extension that will perform the sampling.
What I'm hoping for is something that I can use like this:
var sample = dataset.Sample(100);
var smallSample = smallDataset.Sample(100);
Assert.IsTrue(dataset.Count() > 100);
Assert.IsTrue(sample.Count() == 100);
Assert.IsTrue(smallDataset.Count() < 100);
Assert.IsTrue(smallSample .Count() == smallDataset.Count());
The composition I started with, but only works some of the time is this:
var sample = dataset
.Select((v,i) => new Tuple<string, int>(v,i))
.Where(t => t.Item2 / (double)(dataset.Count() / SampleSize) % 1 != 0)
.Select(t => t.Item1);
This works when the dataset and the sample size share a common devisor and the sample size is greater than 50% of the dataset size. Or something like that.
Any help would be excellent!
Update: So I have the following non-LINQ logic that works, but I'm trying to figure out if this can be "LINQ'd" somehow.
var sample = new List<T>();
double sampleRatio = dataset.Count() / sampleSize;
for (var i = 0; i < dataset.Count(); i++)
{
if ((sample.Count() * sampleRatio) <= i)
sample.Add(dataset.Skip(i).FirstOrDefault();
}
I can't find a satisfactory LINQ solution, mainly because iterating LINQ statements are not aware of the length of the sequence they work on -- which is OK: it totally fits LINQ's deferred-execution and streaming approach. Of course it's possible to store the length in a variable and use this in a Where statement, but that's not in line with LINQ's functional (stateless) paradigm, so I always try to avoid that.
The Aggregate statement can be stateless and length-aware, but I tend to find solutions using Aggregate rather contrived and hard to read. It's nothing but a covert stateful loop; for and foreach take some more lines, but are far easier to follow.
I can offer you an extension method that does what you want:
public static IEnumerable<T> TakeProrated<T>(this IEnumerable<T> sequence, int numberOfItems)
{
var local = sequence.ToList();
var n = Math.Min(local.Count, numberOfItems);
var dist = (decimal)local.Count / n;
for (int i = 0; i < n; i++)
{
var index = (int)(Math.Ceiling(i * dist));
yield return local[index];
}
}
The idea is that the required distance between items is first calculated. Then the requested number of items is returned, each time roughly skipping this distance, sometimes more, sometimes less, but evenly distributed. Using Math.Ceiling or Math.Floor is arbitrary, they either introduce a bias toward items higher in the sequence, or lower.
I think I understand what you're looking for. From what I understand, you're looking to return only a certain quantity of entities in a dataset. As my comment to your original post asks, have you tried using the Take operator? What you're looking for is something like this.
// .Skip is optional, but you can use it with it.
// Just ensure that instead of .FirstOrDefault(), you use Take(quantity)
var sample = dataSet.Skip(amt).Take(dataSet.Count() / desiredSampleSize);
Background -
I am new to programming in C# and am trying to code a custom indicator. On a trading platform that uses C#. A histogram with
positive Y axis = reqAskArraySum
negative Y axis = reqBidArraySum
The inbuilt compiler shows no errors. However the desired results do not seem to show up.
I know/it is possible there are some platform specific initialization problems i.e. code that I have not entered yet correctly.
Question -
The question here is with regards to the code posted below , which is a part of the whole code.
I would like to know whether the posted code satisfies the below objectives.
The objective here is to get a 'number' using a method.
Then only accept selected 'numbers' into an array. The selection/filtration is done by an 'If' statement
Any help and pointers would be highly appreciated.
int i=0;
double iAskSize = GetLevel2Size(ASK,0); //GetLevel2Size(ASK,0) is the method that helps me to retrieve the ASK side 'numbers'//
double iBidSize = GetLevel2Size(BID,0); //GetLevel2Size(BID,0) is the method that helps me to retrieve the BID side 'numbers' //
if(iAskSize>=AskTH_value) //the number should be >= user defined AskTH_value, this is the filtration of the Ask Side 'numbers'//
I am trying to get the filtered iAskSize 'numbers' into the array
reqAskSize, I believe there is a problem here. However I am not sure
{
double[] reqAskSize = new double[1000];
double reqAskArraySum = 0;
for(i=0;i<reqAskSize.Length;i++)
{
reqAskArraySum = reqAskArraySum + reqAskSize[i];
}
SetValue(0,reqAskArraySum);
}
if(iBidSize>=BidTH_value) **//the number should be >= user defined BidTH_value,this is the filtration of the Bid Side 'numbers'//**
I am trying to get the filtered iBidSize 'numbers' into the array
reqBidSize, I believe there is a problem here. However I am not sure
{
double[] reqBidSize = new double[1000];
double reqBidArraySum = 0;
for(i=0;i<reqBidSize.Length;i++)
{
reqBidArraySum = reqBidArraySum + reqBidSize[i];
}
SetValue(1,-reqBidArraySum);
}
If you are trying to add selected numbers into an array, once a number has been selected (through a conditional like if/else), the number should be set in the array.
For example
int[] array = new int[6];
for(int val = 0; val < 6; val++)
{
if(array[val] > 0)
array[val] = 6;
}
Also to obtain a numeral, a return statement makes clear if anything is got.
You should try and see where a return statement may belong within your code.
Working on a clustering project, I stumbled upon this, and I'm trying to figure out if there's a better solution than the one I've come up with.
PROBLEM : Given a List<Point> Points of points in R^n ( you can think at every Point as a double array fo dimension n), a double minDistance and a distance Func<Point,Point,double> dist , write a LINQ expression that returns, for each point, the set of other points in the list that are closer to him than minDistance according to dist.
My solution is the following:
var lst = Points.Select(
x => Points.Where(z => dist(x, z) < minDistance)
.ToList() )
.ToList();
So, after noticing that
Using LINQ is probably not the best idea, because you get to calculate every distance twice
The problem doesn't have much practical use
My code, even if bad looking, works
I have the following questions:
Is it possible to translate my code in query expression? and if so, how?
Is there a better way to solve this in dot notation?
The problem definition, that you want "for each point, the set of other points" makes it impossible to solve without the inner query - you could just disguise it in clever manner. If you could change your data storage policy, and don't stick to LINQ then, in general, there are many approaches to Nearest Neighbour Search problem. You could for example hold the points sorted according to their values on one axis, which can speed-up the queries for neighbours by eliminating early some candidates without full distance calculation. Here is the paper with this approach: Flexible Metric Nearest Neighbor Classification.
Because Points is a List you can take advantage of the fact that you can access each item by its index. So you can avoid comparing each item twice with something like this:
var lst =
from i in Enumerable.Range(0, Points.Length)
from j in Enumerable.Range(i + 1, Points.Length - i - 1)
where dist(Points[i], Points[j]) < minDistance
select new
{
x = Points[i], y = Points[j]
};
This will return a set composed of all points within minDistance of each other, but not exactly what the result you wanted. If you want to turn it into some kind of Lookup so you can see which points are close to a given point you can do this:
var lst =
(from i in Enumerable.Range(0, Points.Length)
from j in Enumerable.Range(i + 1, Points.Length - i - 1)
where dist(Points[i], Points[j]) < minDistance
select new { x = Points[i], y = Points[j] })
.SelectMany(pair => new[] { pair, { x = pair.y, y = pair.x })
.ToLookup(pair => pair.x, pair => pair.y);
I think you could add some bool Property to your Point class to mark it's has been browsed to prevent twice calling to dist, something like this:
public class Point {
//....
public bool IsBrowsed {get;set;}
}
var lst = Points.Select(
x => {
var list = Points.Where(z =>!z.IsBrowsed&&dist(x, z) < minDistance).ToList();
x.IsBrowsed = true;
return list;
})
.ToList();
I have these arrays:
string[] Line1= data[3].ToString().Split(' ');
string[] Line2= data[4].ToString().Split(' ');
The string array contain only integer values. Data are like -20 -30 -12 0 10 20 30 and so on.
Now want to add these values which is in lineNeg1 to Devexpress Chart Control Series without loop.
As right now things are working but due to loop, system gets too slow. Code sample is here under:
for (int i = 0; i < Line1.Length; i++)
{
int y = int.Parse(Line1[i]);
SeriesPoint pt = new SeriesPoint(i, y);
chartControl1.Series[0].Points.Add(pt);
}
Is there any way that i can do something like: Add string array to series without using loop
maybe like: series[0].addrange[Line1] <- Maybe this kind of something option is available
I know the state is wrong, still just want to give an idea of what i am looking for.
You could use Linq:
int[] ints = Line1.Select(x => int.Parse(x)).ToArray();
It's still a for-loop, but now it's hidden! The compiler needs to convert the strings into ints one by one as they're fundamentally different things and stored quite differently. Strings are objects whereas integers are native types. It's not like Javascript or PHP where strings and integers get converted on the fly unfortunately. So this doesn't help you much, it's just semantic sugar.
Now, as far as adding the series goes, maybe the problem is that the chart redraws every time a point is added. Have you tried your code like this:
chartControl1.SuspendLayout();
for (int i = 0; i < Line1.Length; i++)
{
int y = int.Parse(Line1[i]);
SeriesPoint pt = new SeriesPoint(i, y);
chartControl1.Series[0].Points.Add(pt);
}
chartControl1.ResumeLayout();