ColdFusion floor Function After Division [duplicate] - coldfusion

Today I come across unexpected behavior or lack of knowledge with ColdFusion 9,10,11 Round function here is my scenario
Round(28.5) ---> result is 29 expected
Round(0.285*100) ---> result is 28 not expected
Round(precisionEvaluate(0.285*100)) ---> result is 29 using precisionEvaluate!
Round(Evaluate(0.285*100)) ---> result is 29 using Evaluate!
This is not big decimal, why I would need to use precisionEvaluate or Evaluate on a number?
On farther research I found more interesting behavior
Round(0.285*100) result is 28 --WHY? I'm expecting 29-- !
Round(0.295*100) result is 30 ---- Correct !
Round(0.275*100) result is 28 ---- Correct !
Round(0.185*100) result is 19 ---- Correct !
Round(0.385*100) result is 39 ---- Correct !
What is is big deal with 0.285*100?

It's not the precision of the decimal numbers, it's how the underlying floats are stored in Java. This demonstrates:
<cfoutput>
<cfloop array="#[0.275,0.285,0.295]#" index="s">
#s.getClass().getName()#
<cfset f1 = s + 0>
#f1.getClass().getName()#
#f1.toString()#
<cfset f2 = f1*100>
#f2.toString()#
#round(f2)#<br>
</cfloop>
</cfoutput>
Output:
java.lang.String java.lang.Double 0.275 27.500000000000004 28
java.lang.String java.lang.Double 0.285 28.499999999999996 28
java.lang.String java.lang.Double 0.295 29.5 30
I can only assume under the hood CF uses better precision when converting from a string to a float when performing <cfset f1 = s + 0> as there's no dodgy rounding there. However having performed the multiplication step we're getting an accuracy error bleeding in. 28.5 ends up being just shy of 28.5, so rounds to 28 not 29. It's just a binary fraction arithmetic issue.
BTW, there's nothing special about 0.285. A lot of numbers are similarly effected (have a look at the range from 0.005 to 5.05). You just happened to pick a bunch that aren't (other than 0.285).

Related

Python rounding error for ints in a list (list contains ints and strings)

I have a python (2.7) script that reads an input file that contains text setup like this:
steve 83 67 77
The script averages the numbers corresponding to each name and returns a list for each name, that contains the persons name along with the average, for example the return output looks like this:
steve 75
However, the actual average value for "steve" is "75.66666667". Because of this, I would like the return value to be 76, not 75 (aka I would like it to round up to the nearest whole integer). I'm not sure how to get this done... Here is my code:
filename = raw_input('Enter a filename: ')
file=open(filename,"r")
line = file.readline()
students=[]
while line != "":
splitedline=line.split(" ")
average=0
for i in range(len(splitedline)-1) :
average+=int(splitedline[i+1])
average=average/(len(splitedline)-1)
students.append([splitedline[0],average])
line = file.readline()
for v in students:
print " ".join(map(str, v))
file.close()
While your code is very messy and should be improved overall, the solution to your problem should be simple:
average=average/(len(splitedline)-1)
should be:
average /= float(len(splitedline) - 1)
average = int(round(average))
By default in Python 2.x / with two integers does flooring division. You must explicitly make one of the parameters a floating point number to get real division. Then you must round the result and turn it back into an integer.
In Python 3 flooring division is //, and regular division is /. You can get this behavior in Python 2 with from __future__ import division.

ColdFusion chr() does not work with high ascii numbers

I am trying to use a cent sign in my ColdFusion program. It appears to be ascii 155. The function Chr() only interprets values up to 127, although the documentation says otherwise. I found a clue in that I may need to enable high ascii characters in the ColdFusion administrator, but I could not find a place to do that. This codes works:
<cfset x = Chr(127)>
<cfoutput> this is what you get with #x# </cfoutput>
I get a nice box. But this returns only a blank:
<cfset x = Chr(155)>
<cfoutput> this is what you get with #x# </cfoutput>
How do I get Chr() working with higher numbers?
The "cent sign" is ¢, which is chr(162) (which works fine) or ¢ as a HTML entity.
If you want the › symbol then use chr(8250) or ›.
Looks like the standard american ascii chr that we are all used to, and coldfusion chr numbering do not match up.
According to the Livedocs (version 8)
ColdFusion MX: Changed Unicode support: ColdFusion supports the Java UCS-2 representation of Unicode characters, up to a value of 65535. (Earlier releases supported 1-255.)
If you look here, this blog shows some of CF's and the HTML equiv... so you can find some of them more easily.
cf and html entities
Out of interest, i made a simple loop, and thought i'd look through them, and there are plenty of chars... the hard part is finding the right one.
162 is a cent though, as stated in another answer, but this might help explain why.
<cfoutput>
<cfloop index="i" from="1" to="10000">
<pre>Chr #i# = #chr(i)#</pre>
</cfloop>
</cfoutput>
Java UCS-2 has lots of weird characters, as you can see here.
Some Sample output:
Chr 2922 = ୪
Chr 2923 = ୫
Chr 2924 = ୬
Chr 2925 = ୭
Chr 2926 = ୮
Chr 2927 = ୯
Chr 2928 = ୰
Chr 2929 = ୱ
Chr 3207 = ಇ
Chr 3208 = ಈ
Chr 3209 = ಉ
Chr 3210 = ಊ
Chr 3211 = ಋ
Chr 3212 = ಌ

In ColdFusion, is there a numberFormat() mask to drop the decimal if it is 0?

I'm trying to format numbers so that 2 decimal places show up, unless it is a whole number - then I don't want a decimal point to show. I've tried 0.00, _.__, 9.99 and several combinations. Is there a mask for the numberFormat function that can get this result?
<cfif int(x) eq x>
#int(x)#
<cfelse>
#DecimalFormat(x)#
</cfif>
You could divide the variable by 1 and then the whole number is shown without a decimal place.
<cfset a = 5.00>
<cfset b = 5.55>
<cfoutput>#a/1#, #b/1#</cfoutput>
Output is 5, 5.55. Instead of 5.00, 5.55 if you don't divide by 1.
I do not think there is an existing function, but this rounding example might do the trick:
round(yourNumber * 100) / 100
EDIT:
As JasonM mentioned in the comments this will not produce two decimal places for numbers like 1.1.
Ok, I know this question is years old and my solution is dumb as hell but it worked for my needs:
#replace(dollarformat(list_price), '.00', '')#
I know this was dollarformat not number format, but the concept is the same.
LOL. If it's dumb and it works it's not dumb, right?
Still super gross. WTF Adobe?
#REReplace(REReplace(DecimalFormat(value), "0+$", "", "ALL"), "\.+$", "")#
credit: http://www.webveteran.com/blog/web-coding/coldfusion/trimming-a-decimal-with-coldfusion-regex/
I know it's been ages, but if you first do the Numberformat of the value, then Trim it, you will get the desired result ... NumberFormat makes it have trailing digits after the decimal - TRIM will eliminate the trailing decimals if they are just zeroes.
5.55 would result in 5.55 , 5.00 would result in 5 , 5.5 would result in 5.5
etc
I prefer my code as flat as a pancake and try to avoid conditionals whenever possible. So if you feel comfortable dropping down a level to Java you can use DecimalFormat to get the results you want.
<cfset n = JavaCast("double", 1.0) />
<cfset x = CreateObject("java", "java.text.DecimalFormat").init() />
<cfset x.applyPattern("##.##") />
<cfset y = x.format(n) />
The following one liner would also work.
<cfset y = CreateObject("java", "java.text.DecimalFormat").init( "##.##" ).format( JavaCast("double", 1.0) ) />
I'd use precisionEvaluate() + numberFormat() + replaceFirst(regex)
<cfscript>
numberFormat( precisionEvaluate( num ), '_.00' ).replaceFirst( '\.00$', '' );
</cfscript>
For example:
50.00 -> 50
0.00 -> 0
0.001 -> 0
0.006 -> 0.01
123.45 -> 123.45
4/3 -> 1.33
5.24596 -> 5.25
pi() -> 3.14
12345678901234567890 -> 12345678901234567000
reReplace(numberFormat(val, "__.00"), "\.00$", "")

understanding precision and scale on a property

property name="poiLat" length="60" ormtype="big_decimal" persistent=true precision="16" scale="14" default="0" hint="";
I don't understand precision or scale correctly. Using the property above why would '1' give an error and '2' be accepted? what should I change it to to accept '1'
1 ) -118.27 = error
2) -18.27 = ok
Scale refers the number of digits to the right of the decimal place. If you have precision 16 and scale 14, you can only have 2 digits to the left of the decimal place, so
18.12345678901234 = ok
118.27 = error
Try:
precision="16" scale="13"
That will allow 118.1234567890123, but that is a lot of decimal places. How many do you really need?
precision="16" scale="4"
Will allow 123456789012.1234

ColdFusion paging and page numbers

I have a list of user comments stored in a database and I'm displaying 10 per page. On page load I need to dynamically render the appropriate amount of page numbers. At first I thought I would just get the total amount of comments and divide that by 10 to get the # of pages. That however doesn't work correctly. For example:
1. 1-10
2. 11-21
3. 22-32
4. 33-43
5. 44-54
6. 55-65
7. 66-76
So basically with my original math if I have 70 results I will have 7 pages, but if I have 71 results I get 8 pages, which obviously isn't correct. How can I fix this?
Here's my original code:
<cfset commentsNumber = getComments.recordcount / 10>
<cfloop from="1" to="#commentsNumber#" index="i" >
<cfoutput>
#i#
</cfoutput>
</cfloop>
Edit: I can't do math today :(
...if I have 71 results I get 8 pages, which obviously isn't correct.
10 results per page w/ 71 results is 8 pages. What's wrong?
If you want to be sure of your record paging in ColdFusion, you could use an open source library like Pagination.cfc. It handles all the math for you and gives you a customizable display.
hey correct you math first.. :) your example is wrong.
If you are showing 10 comments per page then it should be
1. 1-10
2. 11-20
3. 21-30
etc
By the way you can use CFGRID for paging... it's very simple..