Modulos function in freemarker truncating result - freemarker

I'm trying to make a "complex calculation" in a freemarker template. The calculation calls for a modulus call. At first I kept simplifying my code, and finally just hardcoding values to try and figure out the cause, but it seems that freemarker's mod function ALWAYS returns int values?? but they're not even rounded, they're truncated. I need them rounded (.5 up would work). My most simplified code that does NOT work is this:
<#assign p_year_m1 = (2503.638 % 7.00)?float>
the longer version is:
<#assign p_year_m1 = ((bdy_m1 + (bdy_m1/4.0)-(bdy_m1/100.0)+(bdy_m1/400.0)))%7>
So the correct answer should be 4.638, rounds up to 5, but I'm getting 4.00 even if I wrap ?string[0.00] around it.
What am I missing? Surely there has to be a way to make this work! If not, I guess I'd need help constructing a work around to get similar results.
Thanks.
PS - the var, p_year_m1 is not intialized before this, so I believe if I try to store a float in there it should hold a float.
This is the calculation I'm trying to replicate

I can confirm that % gives the remainder of integer division. It casts (truncates) both arguments to integers, and then calculates the remainder. It's weird for sure, but can't be changed because of backward compatibility. The main application is calculating "zebra tables" and such, where it's might as well desirable, I don't know... it had just get in like that in the early times of the project, and then stuck.

Related

Division of two numbers in freemarker - incorrect result

I'm using freemarker 2.3.26 with Kotlin. I have two variables in my template and I need to divide them.
Variable ${a} is Int and its value is 28.
Variable ${b} is Int and its value is 5.
Output of ${a/b} should be 5, but really it is 6.
I've found out that this is probably caused by rounding
28/5 = 5.6 = rounds to 6
How to correctly handle this? Is there any other - more elegant - way than this?
${(a/b)?floor}
Your number_format configuration setting must be something like '0', hence the decimals are lost when the number is converter to string. I would never use such a number_format, because it's confusing and all. With a usual number_format like '0.####', you get 5.6, because 5 / 6 is indeed 5.6, and if you need to floor it, then you need to be explicit about it. Now, if you are sure you want to drop the decimals during formatting (but again, I think it's a dangerous practice), then use a number_format like '0;;roundingMode=floor' (since FreeMarker 2.3.24), and then ${28/5} will print 5.
Another, probably better solution is that if both numbers are of integer Java types, then you do integer division (like Java). That's possible by setting the arithmetic_engine configuration setting to conservative. That's again not a good practice in general, because the template language doesn't declare the type of the variables, so it's not obvious what a/b will do. As the data-model evolves, and you switch from BigDecimal to an integer Java type, that can lead to wrong output.

Float Domain Error

Just got a "FloatDomainError" in my app, with the message "NaN" where the server would ordinarily describe the offense. The server error page points me to these lines (well, the first one):
n = ((self.weight * (c.percent)/100) / c.package_weight).to_i
n.times do
The problem seems to be with the .to_i, which is meant to convert what totals to 8.35 into an integer so I can do n.times do.
The problem is, if I take to_i away, I get an error telling me, logically enough, that there's no method "times" for the float 8.35. But I don't get why it's not letting me round off 8.35 to an integer. I've tried .floor too, but I get the FloatDomainError.
Ideas on how to round this off so I can get it to work?
Thanks!
This error means that you tried to convert a NaN value to int. NaN stands for "Not a number". That probably meants that your calculation is flawed and not result in 8.35. Maybe the value of c.package_weight is zero and you divide with it.

Xcode - Debugger does not show correct value

Let's try this :
float test = 3.56;
float roundedVal = round(test * 10.0f) / 10.0f;
NSLog (#"%f", roundedVal);
Why does tthe NSLog shows 3.600000, and the debugger 3.5999999 ?
What is the correct value I can count on ?
A float is not very precise and you can't expect them to be displayed accurately from one "view" to the next depending on a variety of factors. Read What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Boils down to this: use double if you really want precision.
The correct value is the debugger. You can see this with a simplified version of the code above:
float test = 3.5999999;
NSLog (#"%f", test);
In this case, you get the same results as what you mentioned above: the log states 3.600000 and the debugger states it is 3.5999999. In all cases, the debugger has the correcrt value over an NSLog. When we dig a bit deeper, we can see that NSLog is slightly massaging the float value.
In reality - you should probably use a double here to maintain the precision you are looking for.
There is no "correct value". The expected value "3.6" does not have an exact binary representation. Therefore, the value the computer uses internally is an approximation. When printing the value, it needs to convert that back to decimal. In your case, the binary representation is likely slightly less than 3.6. NSLog happens to round it up, while the debugger rounds it down.
Using double instead of float, like the accepted answer says, does not change anything in this.

Clone detection algorithm

I'm writing an algorithm that detects clones in source code. E.g. if there is a block like:
for(int i = o; i <5; i++){
doSomething(abc);
}
...and if this block is repeated somewhere else in the source code it will be detected as a clone. The method I am using at the moment is to create hashes for lines/blocks and compare them with hashes of other lines/blocks in the same source to see if there are any matches.
Now, if the same block as above was to be repeated somewhere with only the argument of doSomething different, it would not be detected as a clone even though it would appear very much like a clone to you and me. My algorithm detects exact matches but doesn't detect matching blocks where only the argument is different.
Could anyone suggest any ways of getting around this issue? Thanks!
Here's a super-simple way, which might go too far in erasing information (i.e., might produce too many false positives): replace every identifier that isn't a keyword with some fixed name. So you'd get
for (int DUMMY = DUMMY; DUMMY<5; DUMMY++) {
DUMMY(DUMMY);
}
(assuming you really meant o rather than 0 in the initialization part of the for-loop).
If you get a huge number of false positives with this, you could then post-process them by, for instance, looking to see what fraction of the DUMMYs actually correspond to the same identifier in both halves of the match, or at least to identifiers that are consistent between the two.
To do much better you'll probably need to parse the code to some extent. That would be a lot more work.
Well if you're going todo something else then you're going to have to parse to code at least a bit. For example you could detect methods and then ignore the method arguments in your hash. Anyway I think it's always true that you need your program to understand the code better than 'just text blocks', and that might get awefuly complicated.

Correct use of findall/3, especially the first template argument

i know there is a build-in function findall/3 in prolog,
and im trying to find the total numbers of hours(Thrs) and store them in a list, then sum the list up. but it doesnt work for me. here is my code:
totalLecHrs(LN,THrs) :-
lecturer(LN,LId),
findall(Thrs, lectureSegmentHrs(CC,LId,B,E,THrs),L),
sumList(L,Thrs).
could you tell me what's wrong with it? thanks a lot.
You need to use a "dummy" variable for Hours in the findall/3 subgoal. What you wrote uses THrs both as the return value for sumList/2 and as the variable to be listed in L by findall/3. Use X as the first argument of findall and in the corresponding subgoal lectureSegmentHrs/5 as the last argument.
It looks like the problem is that you're using the same variable (Thrs) twice for different things. However it's hard to tell as you've also used different capitalisation in different places. Change the findall line so that the initial variable has the same capitalisation in the lectureSegmentHrs call. Then use a different variable completely to get the final output value (ie the one that appears in sumList and in the return slot of the entire predicate).
You need to use a different variable because Prolog does not support variable reassignment. In a logical language, the notion of reassigning a variable is inherently impossible. Something like the following may seem sensible...
...
X = 10,
X = 11,
...
But you have to remember that , in Prolog is the conjunction operator. You're effectively telling Prolog to find a solution to your problem where X is both 10 and 11 at the same time. So it's obviously going to tell you that that can't be done.
Instead you have to just make up new variable names as you go along. Sometimes this does get a bit annoying but it's just goes with the territory of a logical languages.

Resources