Comment On Reinventing The Round

In a language whose library functions include things like Rate (interest rate per period for an annuity), SYD (sum-of-years' digits depreciation of an asset for a specified period), and IRR (internal rate of return for a series of periodic cash flows), you would imagine that a VB6 programmer would think that maybe ... just maybe ... the designers of VB would be insightful enough to include a function that rounded off numbers. Apparently not all programmers (especially Steve's predecessor) have that kind of intuition. To be fair though, his function is a bit more convenient than Round: global variables are used instead of cumbersome parameters to specify the number of places and fractional portion of a number ... [expand full text]
« PrevPage 1 | Page 2Next »

Re: Reinventing The Round

2005-08-03 14:05 • by oh boy
pr8?

Re: Reinventing The Round

2005-08-03 14:08 • by DZ-Jay
39782 in reply to 39781
Anonymous:
pr8?




p-rate... price rate??



    dZ.

Re: Reinventing The Round

2005-08-03 14:19 • by El Duderino
pr8?  WTF is pr8?

Re: Reinventing The Round

2005-08-03 14:21 • by El Duderino
39784 in reply to 39783

I guess we all wondered the same thing . . .[:'(]

Re: Reinventing The Round

2005-08-03 14:28 • by Imperfect

Notwithstanding the fact that ANY global variables are badbadbad, isn't "intFractions" an undocumented global variable?


Just... wow.

Re: Reinventing The Round

2005-08-03 14:41 • by David
39786 in reply to 39785
Anonymous:

Notwithstanding the fact that ANY global variables are badbadbad, isn't "intFractions" an undocumented global variable?


Just... wow.



 


Really?  How do you do frequently used constants then?  Do you declare them in every method you need them in or do you pass them to every method that needs them as a parameter?  Neither is preferable to maintaining a list of constants at the top of a header file or the body of your program. 

Re: Reinventing The Round

2005-08-03 14:45 • by TheDan666

"Notwithstanding the fact that ANY global variables are badbadbad, isn't "intFractions" an undocumented global variable?"


What about the total incongriguity of a variable named intFractions ?

Re: Reinventing The Round

2005-08-03 14:49 • by evolved

Alex I love the daily wtf, but the vb6 wtf's are just plain old cliche at this point.


This wasn't really that LOL'able IMHO.


 


.j

Re: Reinventing The Round

2005-08-03 14:50 • by Mordac
39789 in reply to 39786
Global *variables* are bad. Global *constants* arent.

Re: Reinventing The Round

2005-08-03 14:51 • by Anonymous the 3rd
39790 in reply to 39786
Anonymous:
Anonymous:

... ANY global variables are badbadbad ...



Really?  How do you do frequently used constants then?



To quibble on a technicality, frequently used constants aren't really variable, are they?  I mean, they may be variables, but they don't change.  That's what makes it (more) permissible to define constants globally.

Re: Reinventing The Round

2005-08-03 14:55 • by .
There's nothing wrong with parameters that often don't change from one
call to the next being replaced with global variables, it makes it
faster because they don't need to get pushed onto the stack every time
you call the function.

Re: Reinventing The Round

2005-08-03 14:56 • by Maurits
39792 in reply to 39791
Anonymous:
There's nothing wrong with parameters that often don't change from one
call to the next being replaced with global variables, it makes it
faster because they don't need to get pushed onto the stack every time
you call the function.




But if you have lots of them, and you never call the associated functions, that's just a waste of space.



Also they lead to hard-to-track bugs involving functions calling each other, and using the same global variable.

Re: Reinventing The Round

2005-08-03 14:58 • by bz922x
Public Function Round_price(curr_price As Double) As Double

...

Round_price = CDbl(curr_price)





I like the safe coding practice.  Always coerce the value to the
output type. Especially when it is already in the output type!



But really, VB6's rounding functions really suck, so every VB system
has re-implemented Round to add need features. This one is just a
particularly hideous, misguided, non-math based, re-implementation.

Re: Reinventing The Round

2005-08-03 14:58 • by Fregas
Global variables!  GAaaaack!!!!

Re: Reinventing The Round

2005-08-03 15:04 • by cm5400
WOW,  this developer needs a swirly...[:P]  Maybe it will clean all the gunk out of his head.[:D]

Re: Reinventing The Round

2005-08-03 15:17 • by John Smallberries
39797 in reply to 39792
Maurits:
Anonymous:
There's nothing wrong with parameters that often don't change from one
call to the next being replaced with global variables, it makes it
faster because they don't need to get pushed onto the stack every time
you call the function.




But if you have lots of them, and you never call the associated functions, that's just a waste of space.



Also they lead to hard-to-track bugs involving functions calling each other, and using the same global variable.


And if one function inadvertantly changes the global....

Re: Reinventing The Round

2005-08-03 15:39 • by David
39798 in reply to 39790
Anonymous:
Anonymous:
Anonymous:

... ANY global variables are badbadbad ...



Really?  How do you do frequently used constants then?



To quibble on a technicality, frequently used constants aren't really variable, are they?  I mean, they may be variables, but they don't change.  That's what makes it (more) permissible to define constants globally.



Sure they are variable.  I run the program once.  I go back, change the value, and run it again.  It just changed.  The fact that they can change at all is the entire reason for using constant variables in the first place rather than just comparing variables to literals.  Regardless I don't see the point of arguing semantics as no one was in the first place.  Maybe the guy I originally replied to wasn't thinking of constants or didn't mean them when he said global variables, but I cringe whenever I see blanket statements like that. 

Re: Reinventing The Round

2005-08-03 15:55 • by Anonymous
That intFractions part is pretty funky. From what I can tell, it
converts numbers like 12.34 to 12 + (34 / intFractions). Why anyone
would ever want to store fractions in a floating point value like that
I have no idea... and why the weird special treatment for
intFractions=32?

Re: Reinventing The Round

2005-08-03 16:02 • by Russ
39800 in reply to 39798
Anonymous:
Anonymous:
Anonymous:
Anonymous:

... ANY global variables are badbadbad ...



Really?  How do you do frequently used constants then?



To quibble on a technicality, frequently used constants aren't really variable,
are they?  I mean, they may be variables, but they don't
change.  That's what makes it (more) permissible to define
constants globally.



Sure they are variable.  I run the program once.  I go
back, change the value, and run it again.  It just changed. 
The fact that they can change at all is the entire reason for using
constant variables in the first place rather than just comparing
variables to literals.  Regardless I don't see the point of
arguing semantics as no one was in the first place.  Maybe the guy
I originally replied to wasn't thinking of constants or
didn't mean them when he said global variables, but I cringe
whenever I see blanket statements like that. 





You are kidding, right? I hardly think modifying source code and
recompiling means that a constant isn't a constant. And the main reason
for using constants is that sprinkling numbers all over your code
obfuscates meaning and reduces readability. Or, if you're using
strings, reducing the opportunities for inconsistent spelling and
typos. Being able to change a value in one place is an important, but
definitely secondary, benefit.



Re: Reinventing The Round

2005-08-03 16:10 • by Nick
39801 in reply to 39786
variables != constants. use a global constant for constants ...

Re: Reinventing The Round

2005-08-03 16:12 • by Nick
39803 in reply to 39798
Anonymous:
Anonymous:
Anonymous:
Anonymous:

... ANY global variables are badbadbad ...



Really?  How do you do frequently used constants then?



To quibble on a technicality, frequently used constants aren't really variable,
are they?  I mean, they may be variables, but they don't
change.  That's what makes it (more) permissible to define
constants globally.



Sure they are variable.  I run the program once.  I go
back, change the value, and run it again.  It just changed. 
The fact that they can change at all is the entire reason for using
constant variables in the first place rather than just comparing
variables to literals.  Regardless I don't see the point of
arguing semantics as no one was in the first place.  Maybe the guy
I originally replied to wasn't thinking of constants or
didn't mean them when he said global variables, but I cringe
whenever I see blanket statements like that. 





Um, that's the definition of a constant--something that's not going to
change *during the run of a program*, as opposed to a variable that
...well, can.



Re: Reinventing The Round

2005-08-03 16:22 • by silverpie
39804 in reply to 39799

The "prices" we're seeing here are stock prices. Apparently, it uses a system where a price in the old-style notation of 32 5/8 would be passed as 32.5 (with intFractions set to 8 in that circumstance, and this function would convert it to the decimal price of 35.625. The denominator of 32 is used for bond quotes, and the special-case code avoids problems with a numerator of 10 or 20 (which would lose a digit in the CStr command). It makes sense for data entry to be in that form: if you have a lot of those numbers to enter, it's quicker; on the other hand, it should immediately be converted to a proper float directly from the entered string.


(Another example of using a float, at least in its string form, in that way is in baseball stats, where .1 and .2 represent one-third and two-thirds of an inning; similarly the cricket usage of overs.balls, with a base of 6.)


But rather than make a string (and there's another foul there--with the CStr function, you are not guaranteed that the decimal separator will be a period, so this code breaks on a lot of international settings), why not just extract the fractional part with curr_price-int(curr_price) and do math on that?

Re: Reinventing The Round

2005-08-03 16:30 • by dubwai
39805 in reply to 39791

Anonymous:
There's nothing wrong with parameters that often don't change from one call to the next being replaced with global variables, it makes it faster because they don't need to get pushed onto the stack every time you call the function.


That's the worst reason to use global variables that I've ever seen.  What's the return on that, you think?


I don't know where you've been but global variables have been the bane of software development for a quite a while.  If you feel that you are smarter than everyone else then go right ahead and have fun when the bugs start rolling in.

Re: Reinventing The Round

2005-08-03 16:34 • by Notshakespeare
39806 in reply to 39791

There's nothing wrong with parameters that often don't change from one call to the next being replaced with global variables, it makes it faster because they don't need to get pushed onto the stack every time you call the function.


Doesn't sound very thread-safe to me...

Re: Reinventing The Round

2005-08-03 17:08 • by loneprogrammer
39808 in reply to 39805
dubwai:

Anonymous:
There's nothing wrong
with parameters that often don't change from one call to the next being
replaced with global variables, it makes it faster because they don't
need to get pushed onto the stack every time you call the function.


That's the worst reason to use global variables that I've ever seen.  What's the return on that, you think?



It depends on how many times that function gets called.  If the
amount is 300 million times, it might be quite a lot of time
saved.  If the amount is less than a few thousand times, then it
might be so little time that nobody will notice.



Anyway, everybody knows global variables are bad, but Singleton classes are just super awesome great!

Re: Reinventing The Round

2005-08-03 17:12 • by JamesCurran
39809 in reply to 39805
dubwai:

That's the worst reason to use global variables that I've ever seen.  What's the return on that, you think?


I don't know where you've been but global variables have been the bane of software development for a quite a while. 


Not necesarily.  If this is the case as silverpie describes, then intFraction seems to be something that wants to be set once at the start of the program, and used by all calls throughout the run of the program.  If the term "global variable" bothers you, call it a "configuration setting".


 

Re: Reinventing The Round

2005-08-03 17:15 • by dubwai
39810 in reply to 39808
loneprogrammer:
dubwai:

Anonymous:
There's nothing wrong with parameters that often don't change from one call to the next being replaced with global variables, it makes it faster because they don't need to get pushed onto the stack every time you call the function.


That's the worst reason to use global variables that I've ever seen.  What's the return on that, you think?



It depends on how many times that function gets called.  If the amount is 300 million times, it might be quite a lot of time saved.  If the amount is less than a few thousand times, then it might be so little time that nobody will notice.


Anyway, everybody knows global variables are bad, but Singleton classes are just super awesome great!


I'm asking what's the return on a single call.  We can easily multiply that.


When I've done tests on stuff like this on my laptop, I ususally see results on the order of nano-seconds.  i.e. you have to run 1 million times just to see a change on the millisecond scale.  THe other thing you've left out is 300 million times over what time frame?  1 year, one second?  It makes a big difference especially since most applications are idle for a large portion of their run-times.

Re: Reinventing The Round

2005-08-03 17:20 • by dubwai
39811 in reply to 39809
JamesCurran:
dubwai:

That's the worst reason to use global variables that I've ever seen.  What's the return on that, you think?


I don't know where you've been but global variables have been the bane of software development for a quite a while. 


Not necesarily.  If this is the case as silverpie describes, then intFraction seems to be something that wants to be set once at the start of the program, and used by all calls throughout the run of the program.  If the term "global variable" bothers you, call it a "configuration setting".



I was responding to a post that claimed that using globals to avoid putting variables on the stack was a good approach.  Ignoring that there are other ways to not use the stack without globals, that is a really bad case of premature optimization / micro-optimization.

Re: Reinventing The Round

2005-08-03 17:23 • by Rank Amateur
39812 in reply to 39799

Anonymous:
That intFractions part is pretty funky. From what I can tell, it converts numbers like 12.34 to 12 + (34 / intFractions). Why anyone would ever want to store fractions in a floating point value like that I have no idea... and why the weird special treatment for intFractions=32?


Thanks for asking first, because my pathetic humanoid brain sure couldn't figure it out. I expected it to round to the nearest fraction (e.g., 0.25, 0.50, 0.75, 0.00 for intFractions = 4). But no. Then I though maybe it was supposed to get the numerator of a given denominator (intFractions), maybe to represent NYSE prices in some weird way. Uh-uh.


intFractions = 4


round_to_digits = 2


Round_price(3.719) -> 182.75


WTF kind of price rounding is that?


--RA

Re: Reinventing The Round

2005-08-03 17:29 • by jeremydwill
39813 in reply to 39809
JamesCurran:
dubwai:

That's the worst reason to use global variables that I've ever seen.  What's the return on that, you think?


I don't know where you've been but global variables have been the bane of software development for a quite a while. 


Not necesarily.  If this is the case as silverpie describes, then intFraction seems to be something that wants to be set once at the start of the program, and used by all calls throughout the run of the program.  If the term "global variable" bothers you, call it a "configuration setting".


 



That is just fine, but then the safer thing to do is place the "configuration setting" behind a method (function) that does not permit changing the value after it has been set initially. A global variable means that the value can be modified from any routine in the app, which is highly undesirable. The principle is called encapsulation (or information hiding for all you Steve McConnell fans).


Since this is VB6 we are discussing, all that would need to be done is to create a function in a module that returns the configuration setting (or it could be a read-only property, although most people do not seem to know that you can have properties in modules in VB6). Yes, there would be overhead to this call versus directly accessing a variable, but I would favor safety over speed. As one of my favorite authors (Joe Celko) says "I can get great performance if i do not have to get the right answer".

Re: Reinventing The Round

2005-08-03 17:35 • by Russ
39814 in reply to 39808
loneprogrammer:
dubwai:

That's the worst reason to use global variables that I've ever seen.  What's the return on that, you think?



It depends on how many times that function gets called.  If the
amount is 300 million times, it might be quite a lot of time
saved.  If the amount is less than a few thousand times, then it
might be so little time that nobody will notice.



Anyway, everybody knows global variables are bad, but Singleton classes are just super awesome great!




The function would have to be called a lot.
I just whipped up a couple of trivial C programs that call a function
300 million times, the only difference being one of them passes a
couple of long ints and the other one uses globals. Compiled with no
optimisation, the speed difference is about 0.3 seconds. Compiled with
the -O3 flag, that comes down to about 3/1000ths, on average (over
about 10 executions of each app). I'm hard pressed to think of any
situation, even in realtime or embedded application spaces, where a
speed penalty of 3/1000ths of a second over 300 million distinct
function calls is going to make a difference.

Re: Reinventing The Round

2005-08-03 17:41 • by Rank Amateur
39815 in reply to 39812
Rank Amateur:

Anonymous:
That intFractions part is pretty funky. From what I can tell, it converts numbers like 12.34 to 12 + (34 / intFractions). Why anyone would ever want to store fractions in a floating point value like that I have no idea... and why the weird special treatment for intFractions=32?


Thanks for asking first, because my pathetic humanoid brain sure couldn't figure it out. I expected it to round to the nearest fraction (e.g., 0.25, 0.50, 0.75, 0.00 for intFractions = 4). But no. Then I though maybe it was supposed to get the numerator of a given denominator (intFractions), maybe to represent NYSE prices in some weird way. Uh-uh.


intFractions = 4


round_to_digits = 2


Round_price(3.719) -> 182.75


WTF kind of price rounding is that?


--RA



Wait! I just figured it out! It's for pricing airline tickets.


No, seriously, it's when curr_price's decimal digits represent the numerator of a given denominator stored in intFractions. It only works when curr_price goes out to <= 2 decimal places (after being Cstr-ed), and intFractions is <= 32. For example, if intFractions is 16, Round_price will convert a curr_price of 3.12 to its true value of 3.75 (with round_to_digits >= 2). That's why inFractions is global --there must be a function somewhere that converts 3.75 to 3.12 for intFractions of 16 (or 3.06 for intFractions of 8... or 3.6, either would work), and this way you can be sure <cough, cough> that both use the same intFractions.


But... why?


--RA

Re: Reinventing The Round

2005-08-03 17:52 • by El Duderino
39816 in reply to 39812

So I fiddled with the code and in addition to the purposeless use of global variables it's terribly overloaded.  If you set intFractions to 0 it performs simple rounding.  However, for stock prices the source data might store 12.5 where intFractions = 8 to represent 12 5/8.  The second half of the function deals with that transformation -- that's all kosher assuming that they have no control over the format of the source data (WTFs breed more WTFs.)


However, the function shouldn't have attempted to perform both of these requirements.  One function rounds and another handles fractional data -- please don't spaghetti it all together.


I also have a theory behind pr8:  pr1 through pr7 were all previously defined as global variables. [:'(]


 


 

Re: Reinventing The Round

2005-08-03 18:06 • by boohiss
I know your CS professors always say "RAWR GLOBAL VARIABLES BAAAAD", but don't automatically dismiss the usefullness of global variables in certain situations.

This awful rounding function isn't one of those situations, but I'm just saying.

Re: Reinventing The Round

2005-08-03 18:27 • by Mike Weller
39818 in reply to 39817
For some reason IE7 beta1 has flagged this as a potential phishing site :P

Don't worry though, it did the same with xbox.com. I submitted a form saying it isn't suspiscious.

Re: Reinventing The Round

2005-08-03 18:52 • by WTFer
39819 in reply to 39818
Anonymous:
For some reason IE7 beta1 has flagged this as a potential phishing site :P

Don't worry though, it did the same with xbox.com. I submitted a form saying it isn't suspiscious.


Hi, Ebay customer. For security reason we are asking all our users to
send us their password and email address to the following address
ebay@ebay-scammer.com. That way we can verify your account is currently
active.



Thanks,

Ebay Staff



/I'm so not helping

Re: Reinventing The Round

2005-08-03 19:43 • by phelyan
Sorry, I started crying when he started with the decimal point in the string...



"Constants aren't. Variables don't."

Re: Reinventing The Round

2005-08-03 19:57 • by Andrei
 
Anonymous:
I know your CS professors always say "RAWR GLOBAL VARIABLES BAAAAD", but don't automatically dismiss the usefullness of global variables in certain situations. This awful rounding function isn't one of those situations, but I'm just saying.


I actually find great use in having a static global class for multithreaded applications.

Basically, having a program ID, a vector of separate threads comes in handy - that's how I got my server to work. Also, when having a GUI app in java, which can be dozens of levels deep (Below is an example), having global variables can easily tie a controller. Separate the gui and the driver code.

And an example of gui?
The application is a panel, which has multiple faces, each face having different panels grouping the data logically, and each panel has a layout that logically separates the component, each of which has multiple buttons and drivers.

Having a central driver makes all of that simply "globalData.client.lobby.tableList.tables[0].seat[0].user = new user"

And yes, I actually have code like that.

Re: Reinventing The Round

2005-08-03 20:18 • by Maestro
39822 in reply to 39821

CLng from mircrosoft is rubbish... It rounds to the nearest even number when the decimal component equals 0.5.  The Round function mentioned in this WTF is not available in all VB development environments so writing your own needs to be done.  This function has been taken out of context to the environment in which it was developed.


The rounding I use (when neccessary) is as follows (assuming two decimal places):


newvalue = fix(oldvalue*100+0.5)/100


Fix truncates towards 0 and Int (as used in this WTF) rounds towards a smaller value, which is not good for negative values.

Re: Reinventing The Round

2005-08-03 21:00 • by Gary and the Samoyeds
39823 in reply to 39822
Well, in scientic, mathematical, and
statistical work, that is precisely what you want.  If you always
round 0.5000... up (or down), that introduces a slight bias.



I will admit I don't know what the standard is in financial
calculations.  Is round-to-even wrong?  Do you always round
0.5 -> 1.0?



Re: Reinventing The Round

2005-08-03 21:32 • by whojoedaddy
I wonder if a few people worked on this. Some of the variables are in Hungarian Notation ... some aren't .... oh well who needs consistency.

Re: Reinventing The Round

2005-08-03 21:52 • by Foon
The real problem here is storing currency in floating-point variables. Currency should be stored as an integral number of the lowest unit - cents. Do that, and rounding becomes a non-issue.

Re: Reinventing The Round

2005-08-03 22:08 • by phelyan
39826 in reply to 39825

Foon:
The real problem here is storing currency in floating-point variables. Currency should be stored as an integral number of the lowest unit - cents. Do that, and rounding becomes a non-issue.


Don't get me started on money values and rounding. Another problem is that often a lack of separation of presentation and business layers forces some stupidities:


Standard VAT (17.5%) of 1,515: 265.125
What the user wants to see: 265.13
13 lots of above: 3,446.625 (displayed as 3,446.63)
13 lots if taken from displayed value: 3,446.69


Suddenly you're sixpence out because somewhere the rounded value has been written back into the database. Rounding needs to be done at sane places. And, yes, depending on where and how, either of those values could be considered 'correct'.

Re: Reinventing The Round

2005-08-04 01:11 • by Drak
39828 in reply to 39787
TheDan666:

"Notwithstanding the fact that ANY global variables are badbadbad, isn't "intFractions" an undocumented global variable?"


What about the total incongriguity of a variable named intFractions ?



 


Maybe it's an undocumented global constant, and that's why it is named different from all those variables?


Drak

Re: Reinventing The Round

2005-08-04 02:16 • by rob
39833 in reply to 39828
Doesn't .Net do banker's rounding, by default? Wouldn't you have to re-implement round do get it to do standard arithmetic round?

Re: Reinventing The Round

2005-08-04 02:46 • by Raw
39834 in reply to 39833
There are legitimate reasons for writing your own round function. There are no legitimate reasons to do it in this effed up way, but there are reasons to do it.

Example:
The VB library function is not internationalized. Different countries have different rules. In fact, depending on when you went to school here in Sweden, you may have learned to handle a 5 as either round up, round down or round to nearest even.

There are good reasons for all these variants and which is used is just a convention. Since VB does not do it all these ways, you have to do it.

Re: Reinventing The Round

2005-08-04 03:16 • by phelyan
39836 in reply to 39834
Swiss round to the nearest 5 centimes. Nightmare that was to implement everywhere in the system...

Re: Reinventing The Round

2005-08-04 03:34 • by foxyshadis
39838 in reply to 39833
Anonymous:
Doesn't .Net do banker's rounding, by default?
Wouldn't you have to re-implement round do get it to do standard
arithmetic round?


By default, but it has a flag to switch to standard rounding. I think
it even includes nightmare ones like the swiss in an i18n package, but
don't quote me.

Re: Reinventing The Round

2005-08-04 04:50 • by Justin.
39841 in reply to 39836
phelyan:
Swiss round to the nearest 5 centimes. Nightmare that was to implement everywhere in the system...




Well it shouldn't be!  Just work out the granularity you are
dealing with, convert to it, round, convert back to display values.



Tsch.  Kids today.



Justin.

Database Designer and Java Guru

Re: Reinventing The Round

2005-08-04 05:16 • by phelyan
39842 in reply to 39841

Anonymous:
phelyan:
Swiss round to the nearest 5 centimes. Nightmare that was to implement everywhere in the system...


Well it shouldn't be!  Just work out the granularity you are dealing with, convert to it, round, convert back to display values.

Tsch.  Kids today.

Justin.
Database Designer and Java Guru


Gee, we have to display our self-given titles under the name to instill a sense of importance now?


It becomes a nightmare when you have to do it in 20 different places throughout an organically grown system because every other class uses its own rounding methods.


Phelyan.
Jack Of Some Trades and Not Full Of Self

« PrevPage 1 | Page 2Next »

Add Comment