|
Part of this EnumOperators[^] might be of use, and I think I saw someone else with something similar. But, yes, 'twould be nice if there were an INumeric interface... maybe in the next framework.
This space intentionally left blank.
|
|
|
|
|
I was making it generic to make my life easier in future!
(And I hate runtime type checking)
Thanks for that though, even if I'm not going to use it (I've already changed it back to fixed datatype)
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
|
A lot like mine:
public class MovingAverage
{
private List<int> samples = new List<int>();
private int total = 0;
public int SampleSize { get; private set; }
public decimal Value
{
get
{
return samples.Count == SampleSize? (decimal)total / SampleSize : decimal.MinValue;
}
}
public MovingAverage(int sampleSize = -1)
{
SampleSize = sampleSize;
}
public void Add(int value)
{
if (SampleSize > 0)
{
while (samples.Count >= SampleSize)
{
int remove = samples[0];
samples.RemoveAt(0);
total -= remove;
}
}
samples.Add(value);
total += value;
}
}
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
Ah yes, the good old "you can't do math with generics". There are some little libraries that allow you do it, implemented like a bunch of these:
static T Add<T>(T a, T b)
{
if (typeof(T) == typeof(int))
return (T)(object)((int)(object)a + (int)(object)b);
else if .. etc
}
which makes some people angry, but it works.
Btw, that's my favourite test code for decompilers. That weird double cast is often decompiled incorrectly.
However, I'm going to have to file this all under YAGNI. Apart from highly exceptional circumstances, there are only two types you're ever going to put into your MovingAverage: int and double.
|
|
|
|
|
You are probably right - chances are I'll never use anything except a series of int, returning a decimal.
But it's the principle, damnit!
I like generics where I *might* reuse them, and feel slightly dirty hardcoding datatypes...
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
OriginalGriff wrote: I don't fancy doing that in SQL Why? SQL is extremely good in arithmetic...
I'm not questioning your powers of observation; I'm merely remarking upon the paradox of asking a masked man who he is. (V)
|
|
|
|
|
SQL is neither moving, nor average.
This space intentionally left blank.
|
|
|
|
|
SQL has top(n) and order by for moving and avg(column) for average...
I'm not questioning your powers of observation; I'm merely remarking upon the paradox of asking a masked man who he is. (V)
|
|
|
|
|
Maybe I should have included the joke icon.
But also, is TOP part of the SQL standard?
This space intentionally left blank.
|
|
|
|
|
TOP as is not part of the standard...
There is, however implementations in every SQL I know of...
And of course - just for the fun - it's different in each an every of them...
DB2 - select * from table fetch first 10 rows only
MSSQL - select top(10) * from table
MySQL - select * from table limit 10
I'm not questioning your powers of observation; I'm merely remarking upon the paradox of asking a masked man who he is. (V)
|
|
|
|
|
How about oracle? Without using a subquery that is.
|
|
|
|
|
I don't know Oracle from my experience but a short Googleing shows that it has it's own syntax - as expected...
Oracle - select * from table where rownum <= n
I'm not questioning your powers of observation; I'm merely remarking upon the paradox of asking a masked man who he is. (V)
|
|
|
|
|
Can't do that. Rownum is assigned in the beginning before ORDER BY.
The result would be n random rows.
Think of it as being processed in this order:
1. The FROM/WHERE clause goes first.
2. ROWNUM is assigned and incremented to each output row from the FROM/WHERE clause.
3. SELECT is applied.
4. GROUP BY is applied.
5. HAVING is applied.
6. ORDER BY is applied.
|
|
|
|
|
As I told I do not know Oracle form my own experience - found that bit in Google...
I'm not questioning your powers of observation; I'm merely remarking upon the paradox of asking a masked man who he is. (V)
|
|
|
|
|
It's just one of my pet peeves, that Oracle lacks a limit clause.
It's easy enough to fix with a subquery, I just believe I shouldn't need to.
|
|
|
|
|
Sounds like article fodder to me.
<voice type="Ebeneezer Scrooge"> Bah. dumb bugs </voice>
|
|
|
|
|
I like to call those little divrersions "Flights of fancy" or "Magic Mike moments"
|
|
|
|
|
Since this borders on a programming answer, I'm not going to give you the answer directly, but look at they way the two parameter sum function is implemented.
|
|
|
|
|
Quitter. You could have done it with some creativity using Linq.Expressions.
|
|
|
|
|
I like it ... when you are too clever for your own good. Me learn stuff.
“But I don't want to go among mad people,” Alice remarked.
“Oh, you can't help that,” said the Cat: “we're all mad here. I'm mad. You're mad.”
“How do you know I'm mad?” said Alice.
“You must be," said the Cat, or you wouldn't have come here.” Lewis Carroll
|
|
|
|
|
That's the day not wasted then!
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
I had a similar problem once. (But I was more stubborn keeping it Generic)
So what i ended up doing was keeping with the object types, using that to filter each value and tryparse into decimal List class so that I could sum up everything. I just had to prepare for the worse so I put in my catch that if any error would occur to throw out the value and just log what went wrong, so that way when I picked up more errors (Which I did not much), i could just improve the tryparse
Loading signature...
. . . Please Wait . . .
|
|
|
|
|
You could do it by using a class that does the adding. You would need to specify the class to do the adding and the type it uses in the moving averages class.
Something like this:
public interface IArithmetic<T>
{
T Add(T augend, T addend);
}
public class GenericAdd<T, U> where T : IArithmetic<U>, new()
{
T adder = new T();
public U AddGenericTypes(U augend, U addend)
{
return adder.Add(augend, addend);
}
}
And for each type you want to use this with you will need one of these.
public class AddInt : IArithmetic<int>
{
public AddInt()
{
}
#region IArithmetic<int> Members
public int Add(int augend, int addend)
{
return augend + addend;
}
#endregion
}
These can then be used like this:
GenericAdd<AddInt, int> intAdder = new GenericAdd<AddInt, int>();
int result = intAdder.AddGenericTypes(1, 2);
Seems like a lot of work to me unless you know you are going to need it.
|
|
|
|
|
You could of course go the fully OO route and make your own "number" class. I.e. the way you'd have done it prior to generics. Then add some implied conversion overloads so you don't need to manually type-cast your int/double/decimal/etc. You could then even accommodate other more complicated data types (e.g. to generate moving averages on a candle-stick-chart with 3 values per item: open, avg, close).
BTW, for the data sample I'd go with either a double linked list (LinkedList<t> with max length) or a circular array, not an Array List as you've done in your sample code (that's implemented as a flat array so a remove from index 0 means it shifts all samples down by 1, if you reverse the order then each insert would shift all items up by 1). Seeing as mostly you'd calculate by iterating over each item in the "list" and you'd not want to move all the samples in the array each time you get a new one the linked list should suffice for this purpose. The circular array I'd only use if I know the size sample will not change after initially creating the object and if I need to reference specific items by index.
You could use a Queue<t> type for this, as well. I "think" it's implemented as a linked list anyway.
Here's what I'm thinking:
public class MyNumber {
private object _value;
public object Value {
get { return _value; }
set {
if ((value is int) || (value is double) || (value is decimal))
_value = value;
else throw new InvalidCastException();
}
}
public MyNumber(object val) {
Value = val;
}
public static implicit operator MyNumber(int val) { return new MyNumber(val); }
public static implicit operator int(MyNumber val) { return (int)val._value; }
public static implicit operator MyNumber(double val) { return new MyNumber(val); }
public static implicit operator double(MyNumber val) { return (double)val._value; }
public static implicit operator MyNumber(decimal val) { return new MyNumber(val); }
public static implicit operator decimal(MyNumber val) { return (decimal)val._value; }
}
public class MovingAverage {
private LinkedList<MyNumber> _samples = new LinkedList<MyNumber>();
private decimal total = 0;
public int SampleSize { get; private set; }
public decimal Value {
get {
if (SampleSize < 0) return (_samples.Count > 0) ? total / _samples.Count : 0;
return (_samples.Count >= SampleSize) ? total / (decimal)SampleSize : 0;
}
}
public MovingAverage(int sampleSize = -1) {
SampleSize = sampleSize;
}
public void Add(MyNumber value)
{
_samples.AddLast(value);
total += value;
if (SampleSize > 0) {
while (_samples.Count > SampleSize) {
total -= _samples.First;
_samples.RemoveFirst();
}
}
}
}
Edit: Stupid me that type check should have been or's not and's
modified 10-Feb-14 7:03am.
|
|
|
|