LINQ to Entities integer division incorrect? - linq

I'm trying to do a little partitioning, dividing list entries into 6-month blocks. Using this LINQ to Entities query, I get results that imply that integer division is not taking place:
from e in enrollments
let AgeInHalfYears = e.AgeMonths / 6
select new { e.AgeMonths ,
AgeInHalfYears,
AgeFloor = ((int)AgeInHalfYears) * 6 }
My results are:
AgeMonths AgeInHalfYears AgeFloor
68 11 68
41 7 41
34 6 34
I would have expected 66, 36, and 30 in that last column.
I rewrote the LINQ pretty simply as
AgeFloor = e.AgeMonths - (e.AgeMonths % 6)
But I'm still curious about why the division operation is clearly floating point, even with that (int) cast in there... I wouldn't have expected that.

The Entity Framework is probably ignoring your cast when generating the SQL.
LINQ-based SQL generators are rarely (if ever) perfect.
In particular, .Net's type system is different enough from SQL's that they probably ignore all casts.
Try calling Math.Floor instead.

Related

SQL Server Reporting: How calculate value based on the previous calculated value int the same column?

I'm trying to calculate a row value based on the previous row value in the same column within a report expression. I can't precalculate this from database since starting point of calculation is dependent from input parameters and values in a table should be recalculated dynamically within report itself.
In Excel analogical data and formula look like as it is shown below (starting point is always 100):
B C D E
Price PreviousPrice CalcValue Formula
1 NULL NULL 100
2 2.6 2.5 104 B2/C2*D1
3 2.55 2.6 102 B3/C3*D2
4 2.6 2.55 104 B4/C4*D3
5 2.625 2.6 105 B5/C5*D4
6 2.65 2.625 106 B6/C6*D5
7 2.675 2.65 107 B7/C7*D6
I tried to calculate expected values ("CalcValue" is the name of column where expression is set) like this:
=Fields!Price.Value/ PreviousPrice.Value * Previous(reportitems("CalcValue").Value))
but got an error "Aggregate functions can be used only on report items contained in page headers and footers"
Can you please advice whether expected result is achievable in my case and suggest a solution?
Thank you in advance!
Sadly I'm still facing with issue: calculated column does not consider previous calculated value. E.g., I added CalcVal field with 100 as default and tried to calculate using above approach, like: =previous(runningValue(Fields!CalcVal.Value, sum, "DataSet1") ) * Fields!Price.Value/Fields!PreviousPrice.Value.
But in this case it always multiples Fields!Price.Value/Fields!PreviousPrice.Value by 100..
For example CalcVal on Fly always show 200
=previous(runningValue(Fields!CalcVal.Value, sum, "DataSet1")) * 2
https://imgur.com/Wtg3Wsg
I tried with your sample data, here is how I achieved the results
Formula to use, You might have to take care of null values
=Fields!Price.Value/(Fields!PreviousPrice.Value*Previous(Fields!CalcValue.Value))
Edit: Update to answer after Op's comment
CalcValue is caluated with below formula i.e on the fly
=RunningValue(CountDistinct("Tablix6"),Count,"Tablix6"*100
and then Final value as below
=Fields!Price.Value/(Fields!PreviousPrice.Value*
Previous(RunningValue(CountDistinct("Tablix6"),Count,"Tablix6"))*100)

How do I create a time string from a number of seconds in APL?

I would like to turn a number-of-seconds-since midnight into an HH:MM:SS formatted string.
For example, the number 17672 should turn into the string '04:54:32'. I can do the math to get the integer components, like so:
T←17672
H←⌊T÷3600
MS←3600|T
M←⌊MS÷60
S←60|T
H M S
4 54 32
But I do not know how to join the three components of this array into a string (separated by colons), and left pad each time component with a zero. For example, I would want
6 0 8
to be '06:00:08'.
I can use either GNU APL or the online ngn-apl
In extended APL (all modern APLs) you can use
1↓∊':',¨¯2↑¨⍕¨100+24 60 60⊤T
ngn/apl has a non-conforming ⍕ so you'll need
1↓∊':',¨¯2↑¨,¨⍕¨100+24 60 60⊤T
Try it online!
You in Dyalog, GNU and ngn/apl you can make a dfn (lambda) out of it by enclosing it in braces. Try it in ngn/apl and in Dyalog APL.
Using Dyalog APL version 16.0 or higher, you can use the # operator to place colons:
{1↓':'#4 7∊⍕¨100+24 60 60⊤⍵}
Try it online!
The first step is to improve the calculation by using the "encode"-function:
24 60 60⊤17672
4 54 32
To format these numbers and insert the colon, I typically use ⎕FMT which is a vendor-specific function to format numbers as strings. A general way to do this in most APLs might be this:
a←,⍕3 1⍴24 60 60⊤17672
1↓,':',3 2⍴('0',a)[1+(⍳⍴a)×a≠' ']
04:54:32
Finally, instead of executing this in the session, you could put it into a function:
R←FormatSecs secs;a
a←,⍕3 1⍴60 60 60⊤secs
R←1↓,':',3 2⍴('0',a)[1+(⍳⍴a)×a≠' ']
Let's test it:
FormatSecs 17672
04:54:32
Task accomplished ;-)

numerical recipies ran3 generates negative numbers

I am using numerical recipes scheme to generate random numbers (ran3, page 7 in this PDF file). I didn't notice anything strange but this time, I got a negative numbers at the "warm up" stage which are larger than MBIG. The code look as if this shouldn't happen. I can easily fix this with changing the if statement to be a while statement at the line that says if(mk.lt.MZ)mk=mk+MBIG but I want to know what are the consequences.
Edit:here is the function
FUNCTION ran3a(idum)
INTEGER idum
INTEGER MBIG,MSEED,MZ
C REAL MBIG,MSEED,MZ
REAL ran3a,FAC
PARAMETER (MBIG=1000000000,MSEED=161803398,MZ=0,FAC=1./MBIG)
C PARAMETER (MBIG=4000000.,MSEED=1618033.,MZ=0.,FAC=1./MBIG)
INTEGER i,iff,ii,inext,inextp,k
INTEGER mj,mk,ma(55)
C REAL mj,mk,ma(55)
SAVE iff,inext,inextp,ma
DATA iff /0/
if(idum.lt.0.or.iff.eq.0)then
iff=1
mj=MSEED-iabs(idum)
mj=mod(mj,MBIG)
ma(55)=mj
mk=1
do 11 i=1,54
ii=mod(21*i,55)
ma(ii)=mk
mk=mj-mk
if(mk.lt.MZ)mk=mk+MBIG
mj=ma(ii)
11 continue
do 13 k=1,4
do 12 i=1,55
ma(i)=ma(i)-ma(1+mod(i+30,55))
if(ma(i).lt.MZ)ma(i)=ma(i)+MBIG
12 continue
13 continue
inext=0
inextp=31
idum=1
endif
inext=inext+1
if(inext.eq.56)inext=1
inextp=inextp+1
if(inextp.eq.56)inextp=1
mj=ma(inext)-ma(inextp)
if(mj.lt.MZ)mj=mj+MBIG
ma(inext)=mj
ran3a=mj*FAC
return
END
I was getting Seg Faults (using gfortran 4.8) because the function was trying to change the input value idum from the negative number to 1. There is no reason for that line (nor anything with iff), so I deleted it and printed out the array ma at several different places and found no negative numbers in the array.
One possibility, though, is if iabs(idum) is larger than MSEED, you might have a problem with the line mj=MSEED - iabs(idum). You should protect from this by using mj=abs(MSEED-abs(idum)) like the book has written.
Had a look at the pdf. What you need to do is
1) Seed it: value = ran3(-1)
2) Use it: value = ran3(0)

How can i make this code more time efficient?

This is a part of the Profiler report, and shows how these lines are eating up the time. Can it be improved upon?
434 %clean up empty cells in subPoly
228 435 if ~isempty(subPoly)
169 436 subPoly(cellfun(#isempty,subPoly)) = [];
437
438 %remove determined subpoly points from the hull polygon
169 439 removeIndex = zeros(size(extendedPoly,1),1);
169 440 for i=1:length(subPoly)
376 441 for j=1:size(subPoly{i}(:,1))
20515 442 for k=1:size(extendedPoly,1)
6.12 5644644 443 if extendedPoly(k,:)==subPoly{i}(j,:)
30647 444 removeIndex(k,1)=1;
30647 445 end
1.08 5644644 446 end
0.02 20515 447 end
376 448 end
169 449 extendedPoly = extendedPoly(~removeIndex(:,1),:);
169 450 end
Since Matlab has a tendency to think that everything on the command line is an array of doubles, and assuming that the contents of your arrays and cell arrays are numbers, you can replace
if extendedPoly(k,:)==subPoly{i}(j,:)
removeIndex(k,1)=1;
end
with the equivalent
removeIndex(k,1) = extendedPoly(k,:)==subPoly{i}(j,:)
which might save a few nano-seconds, though I'll be a bit surprised if it saves much more.
I suspect that if I was a little smarter or more diligent I could probably replace your entire loop nest with a single assignment along the lines of
removeIndex = extendedPoly==subPoly
The trick here is to ensure that all the arrays in the expression have the same dimensions.
You're probably approaching a performance limit within the current nesting strategy. The "slow" line only requires 1 usec per execution.
Generally in a set-matching case like this, you are better off sorting both sets, and then performing a single loop through both sets concurrently. (Google "insertion sort" for more on this, also see this related question/answer Optimization of timestamp filter in MATLAB - Working with very large datasets)
It's not immediately obvious how to best apply this to your circumstance. If you post an executable example we could look into this more closely.
Without looking at executable code, it may make sense to expand your subPoly cell of vectors into a single, sorted numeric array (called something like sortedElementsToremove). Then get the sort order from extendedPoly like this: [~, ixsSortExpended] = sort(extendedPoly);.
Now you can use a single loop with two indexes to perform the masking. Something like this (code not tested):
ixExtended = 1; %Index though sort order
for ixSub = 1:length(sortedElementsToremove);
%Use while to update second index
while ...
(extendedPoly(ixsSortExpended(ixExtended)) < sortedElementsToremove(ixSub) ) && ...
ixExtended < length(ixsSortExpended)
ixExtended = ixExtended + 1;
end
if (sortedElementsToremove(ixSub) == extendedPoly(ixsSortExpended(ixExtended)))
removeIndex(ixsSortExpended(ixExtended)) = true;
end
end

Are there sequence-operator implementations in .NET 4.0?

With that I mean similar to the Linq join, group, distinct, etc. only working on sequences of values, not collections.
The difference between a sequence and a collection is that a sequence might be infinite in length, whereas a collection is finite.
Let me give you an example:
var c1 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var c2 = FunctionThatYieldsFibonacciNumbers();
var c3 = c1.Except(c2);
This does not work. The implementation of Except does not work on the basis that the numbers in either collection will be strictly ascending or descending, so it first tries to gather all the values from the second collection into a set (or similar), and only after that will it start enumerating the first collection.
Assuming that the function above is just a While-loop that doesn't terminate unless you explicitly stop enumerating it, the above code will fail with a out-of-memory exception.
But, given that I have collections that are considered to be strictly ascending, or descending, are there any implementations already in .NET 4.0 that can do:
Give me all values common to both (inner join)
Give me all values of both (union/outer join)
Give me all values in sequence #1 that isn't in sequence #2
I need this type of functionality related to a scheduling system I need to build, where I need to do things like:
c1 = the 1st and 15th of every month from january 2010 and onwards
c2 = weekdays from 2010 and onwards
c3 = all days in 2010-2012
c4 = c1 and c2 and c3
This would basically give me every 1st and 15th of every month in 2010 through 2012, but only when those dates fall on weekdays.
With such functions it would be much easier to generate the values in question without explicitly having to build collections out of them. In the above example, building the first two collections would need to know the constraint of the third collection, and the examples can become much more complex than the above.
I'd say that the LINQ operators already work on general sequences - but they're not designed to work specifically for monotonic sequences, which is what you've got here.
It wouldn't be too hard to write such things, I suspect - but I don't believe anything's built-in; there isn't even anything for this scenario in System.Interactive, as far as I can see.
You may onsider the Seq module of F#, which is automatically invoked by using special F# language constructs like 1 .. 10 which generates a sequence. It supports infinite sequences the way you describe, because it allows for lazy evaluation. Using F# may or may not be trivial in your situation. However, it shouldn't be too hard to use the Seq module directly from C# (but I haven't tried it myself).
Following this Mandelbrot example shows a way to use infinite sequences with C# by hiding yield. Not sure it brings you closer to what you want, but it might help.
EDIT
While you already commented that it isn't worthwhile in your current project and accepted an answer to your question, I was intrigued by the idea and conjured up a little example.
It appeared to be rather trivial and works well in C# with .NET 3.5 and .NET 4.0, by simple including FSharp.Core.dll (download it for .NET 3.5) to your references. Here's an out-of-the box example of an infinite sequence implementing your first use-case:
// place in your using-section:
using Microsoft.FSharp.Collections;
using Microsoft.FSharp.Core;
// [...]
// trivial 1st and 15th of the month filter, starting Jan 1, 2010.
Func<int, DateTime> firstAndFifteenth = (int i) =>
{
int year = i / 24 + 2010;
int day = i % 2 != 0 ? 15 : 1;
int month = ((int)i / 2) % 12 + 1;
return new DateTime(year, month, day);
};
// convert func to keep F# happy
var fsharpFunc = FSharpFunc<int, DateTime>.FromConverter(
new Converter<int, DateTime>(firstAndFifteenth));
// infinite sequence, returns IEnumerable
var infSeq = SeqModule.InitializeInfinite<DateTime>(fsharpFunc);
// first 100 dates
foreach (var dt in infSeq.Take(100))
Debug.WriteLine("Date is now: {0:MM-dd-yyy}", dt);
Output is as can be expected, first few lines like so:
Date is now: 01-01-2010
Date is now: 01-15-2010
Date is now: 02-01-2010
Date is now: 02-15-2010
Date is now: 03-01-2010

Resources