[HN Gopher] The most copied StackOverflow snippet of all time is...
___________________________________________________________________
The most copied StackOverflow snippet of all time is flawed (2019)
Author : vinnyglennon
Score : 671 points
Date : 2021-06-16 21:27 UTC (1 days ago)
(HTM) web link (programming.guide)
(TXT) w3m dump (programming.guide)
| bsaul wrote:
| seems that most comments here missed the end of the article ,
| where he points to the "production ready" version of the
| solution, that is indeed very close to the original one,
| including a while loop.
| zoomablemind wrote:
| > ..."production ready" version of the solution, that is indeed
| very close to the original one, including a while loop.
|
| What's missing still is a comprehensive set of test cases to
| check against.
|
| If such cases were spec'ed to go along with the original code,
| fthen at least one could have seen the applicability range and
| perhaps other people would have added some challenging corner
| cases (just as mentioned in the OP).
| t0astbread wrote:
| It's especially ironic given that this is about a StackOverflow
| code snippet that many people probably also copied without
| reading.
| TwoBit wrote:
| Neither is production ready because they have no code comments.
| And if ever there was code requiring comments, this is it.
| eutectic wrote:
| This is why it's a good idea to have a real integer type.
| enriquto wrote:
| Isn't it impossible? Integers go arbitrarily large but
| computers don't.
| Sohcahtoa82 wrote:
| They can go large enough for anything that matters.
|
| A quick Google says there's an estimate of 10^78 to 10^82
| atoms in the universe. That number would be able to be stored
| in well under 300 bits.
| ithinkso wrote:
| Universe is tiny compared to mathematics and software, even
| simply RSA keys are already 2048bit.
|
| Lots of problems suffer from 'combinatorial explosion' [1].
|
| I recently learned about the Archimedes's cattle problem,
| the solution is of order 10^206544 [2]
|
| [1] https://en.wikipedia.org/wiki/Combinatorial_explosion
|
| [2]
| https://en.wikipedia.org/wiki/Archimedes%27s_cattle_problem
| Sohcahtoa82 wrote:
| 10^206544 would still be less than 8 kB. You could store
| it on an Atari cartridge!
| asdf3243245q wrote:
| Computers also go arbitrarily large. Not infinite, but
| arbitrarily large.
|
| A real number type could be bounded by the amount of RAM you
| have.
| alisonkisk wrote:
| You can use disk storage too. And network storage.
| btilly wrote:
| It is possible within the limits of available memory on the
| computer. Rather than the usual limit of a fixed number of
| bits.
|
| I've ironically found that big integer libraries sometimes
| optimize math routines more than string conversion. This was
| quite annoying for me when I optimized the factorial function
| in Ruby, and found that generating the string was my
| bottleneck. I then optimized that as well. :-)
| jrockway wrote:
| > Sebastian then reached out to me to straighten it out, which I
| did: I had not yet started at Oracle when that commit was merged,
| and I did not contribute that patch. Jokes on Oracle. Shortly
| after, an issue was filed and the code was removed.
|
| Good thing it wasn't a range check function. I hear those are
| expensive.
| dokem wrote:
| Something about this comes off as amateurish. The obsession with
| minimization. Just use a switch statement. Now where is the bug
| going to hide? The solution doesn't need to generalize, there is
| only a small handful of different solutions. Just break them all
| out. It's more maintainable and readable and requires less
| thinking.
| TwoBit wrote:
| I don't know why you are being downvoted. The best solution
| here is for the author to admit using log was a bad idea and
| rewrite an entirely different version.
| anonymfus wrote:
| _> return String.format( "%.1f %sB", bytes / Math.pow(unit, exp),
| pre);_
|
| As a human, the first thing that I hate about this interpretation
| of "human readable" format is inconsistency in the number of
| significant digits. One digit after decimal separator is simply
| wrong, as when you jump from 999.9 MB to 1.0 GB you go from 4
| significant digits to 2, instead it should be 1.000 GB, 10.00 GB
| and so on. This annoys me enormously when I upload things to
| Google Drive from Android phone and look at the number of data
| transferred as as soon it becomes bigger than 1 GB digits stop
| changing and I become anxious that it stopped the transfer and my
| Windows Phone nostalgia jumps over the roof (as WP was never
| infected with this problem by virtue of not using Java, and
| OneDrive on WP explicitly showed current connection speed, and
| frozen connection never caused any strange problems with uploaded
| files like it does on Google Drive on Android).
|
| As a human not from US, the second thing I hate here is lack of
| locale parameter to pass to formatter as decimal separator is
| different in different cultures, and in the world of cloud
| computing the locale of the machine where the code is run is
| often different from the one where the message is displayed.
|
| As a human from a culture using non latin alphabet, the third
| thing I hate here should be obvious for a reader.
| cycomanic wrote:
| I don't think it makes sense to talk about significant digits
| here. And while you are correct that you should not go from
| 999.9MB to 1.0 GB you are incorrect about your reasoning and
| your correction is also incorrect. Significant digits signify
| reliability of the numbers. So if your measurement is accurate
| to the +/- 50kB as indicated by 999.9MB you should then move to
| 1.0000 GB (5 significant digits). So it should be 10.00GB and
| 1.00GB not 1.000GB, because the reliability should not change
| between your measurements.
| anonymfus wrote:
| As a bonus, the thing I don't care any more here is that there
| is no option to output binary SI prefixes.
| Kiro wrote:
| > instead it should be 1.000 GB, 10.00 GB and so on
|
| I had a hard time mentally parsing that sequence even when I
| knew what your point was so imagine regular users seeing that.
| stefan_ wrote:
| Why are you writing code? The question was for a static method in
| Apache Commons, not your "I'm so clever" implementation. Think
| the reading comprehension is flawed.
|
| (Of course, this static method exists in Apache Commons, going
| back at least 20 years. But the fellow "code golfers" of the
| author voted someone to the first answer who similarly had the
| irresistible urge to _try to be very clever_. It 's a scourge on
| StackOverflow.)
| opheliate wrote:
| I think that the answer is what I would expect based on the
| question title (which doesn't mention Apache Commons, only
| Java), if I was another user searching for the solution to this
| problem. Maybe the question should have been renamed to
| indicate this, but as it stands, I do think a library-agnostic
| solution is more helpful to people finding the question than an
| answer which only works for Apache Commons.
| css wrote:
| I like the way v8 handles this problem:
| https://github.com/v8/v8/blob/dc712da548c7fb433caed56af9a021...
| devit wrote:
| You have to be a terrible programmer to even consider using a
| base 10 logarithm for this.
|
| Their proposed improvement is also terrible, since it divides
| multiple times unnecessary, and checks for negativity multiple
| times unnecessarily.
|
| The proper simple solution is of course a handwritten binary
| search with if-else blocks that starts with the most likely
| range, annotated with "likely" annotations, and a single
| division.
|
| If this is the main task of the program for a while, and thus a
| large fraction of the cache can be dedicated to it, then
| solutions with large lookup tables are worth trying (obviously
| optimizing string formatting is also essential in this case).
|
| This is why software is so often broken, there's a lot of
| incompetent people programming.
| winrid wrote:
| You're right, however I think they were going for a
| "branchless" version just to see if they could.
| simonw wrote:
| "You have to be a terrible programmer to even consider using a
| base 10 logarithm for this."
|
| That's not a fair statement.
|
| Good programmers are programmers who deliver value - who build
| robust, maintainable features in reasonable time that address
| user needs.
|
| Whether or not you would quickly find the correct approach to
| this specific problem is a miniscule, pedantic detail in a
| giant ocean of programming skills and experiences.
| juped wrote:
| You are replying to a satirical comment, I think.
| Aeolun wrote:
| You may think that, but I'm partial to the 'for-loop version'
| that everybody and their dog can understand.
| hvdijk wrote:
| About the "terrible" aspect of it, to quote: "Granted it's not
| very readable and log / pow probably makes it less efficient
| than other solutions. But there were no loops and almost no
| branching which I thought was pretty neat." No need to insult
| the author over it.
|
| About your "proper simple solution": I don't think that's a
| good idea either. Based on your next paragraph, the version you
| suggest with the handwritten binary search and "likely"
| annotations is for the case where the code isn't performance
| critical: for where the code is performance critical, you
| suggest a different solution. If the code isn't performance
| critical, please do not turn it into an unreadable mess over
| what would become a negligible overall performance gain. Write
| it in a simple, obviously correct way, keep it boring, and
| you'll keep it stable; you can use the time you save on fixing
| bugs in your super optimised version on improving more critical
| parts of your program.
| [deleted]
| GuuD wrote:
| Wait. I always use logarithm for this kind of tasks, how
| exactly does it make me incompetent and terrible? This is
| literally what logarithm represents?
| [deleted]
| aristophenes wrote:
| It disturbs me that the authors answer became the top answer. It
| didn't have a loop but was less efficient than the already
| accepted answer, and worse, much more complicated for a human to
| read and understand. It seems we are always drawn to be clever,
| when perfection is found in simplicity.
| [deleted]
| unwind wrote:
| I must admit I smiled at seeing that I edited the question, back
| in the day. :) Can't say I remember the question, and didn't know
| it has that epic feature of being the most-copied. Cool!
| mweberxyz wrote:
| Say what you want about the stability of the npm ecosystem, but
| if this were JS, a new SemVer patch release could be cut, and it
| would be fixed in thousands of code bases essentially instantly.
| rovr138 wrote:
| and if they get pissed, they can also remove the package and
| break thousands of code bases essentially instantly.
| AgentME wrote:
| NPM hasn't allowed unpublishing packages for years.
| mypalmike wrote:
| And then thousands of scripts that parse the old output would
| start to fail. :-)
| yesenadam wrote:
| > The most copied StackOverflow snippet of all time
|
| Maybe, but sounds like it's merely _the Java snippet from SO
| found most often on github_. Not sure why blog author didn 't
| include the word "Java" in his title or the first paragraph:
|
| > an answer I wrote almost a decade ago was found to be the most
| copied snippet on Stack Overflow
|
| There is no evidence for this claim in the blog post, just that
| it's the "most copied Java snippet". And it's just based on
| occurrences in github. Maybe the most-copied snippet is an AWK or
| ffmpeg one-liner? Something that wouldn't find its way into a
| github repo. Or maybe something undetectably vanilla, like
| answers to "How do you write loops in language X?" Is there a way
| of finding out what actually is the most-copied snippet?
| sgerenser wrote:
| I don't know how you'd find it, but if I had to bet it would be
| something to do with git.
| beermonster wrote:
| > I wrote almost a decade ago was found to be the most copied
| snippet on Stack Overflow. Ironically it happens to be buggy.
|
| I don't find it ironic, I find it quite normal that even small
| snippets of code contains bugs (given the daily review requests I
| receive).
|
| I think when copying code literally from StackOverflow what's
| more important is understanding what the code does, and why ,
| rather than copying it ad-verbatim by copy & pasting it into your
| production code.
|
| I also often find on StackExchange et al that quite often the
| most upvoted is the one that 'fixes it' for 'most people' yet the
| correct answer is down at number 3 or 4. Again, understanding the
| answer and why it applies, helps give you the context to
| understand if this is _actually_ the solution to _your_ problem
| or just treats the symptom.
| megalodon wrote:
| One of the best tips I have gotten from the internet is to
| never copy and paste code you have not written yourself. Even
| rewriting it verbatim makes you think about what it is you are
| actually copying.
|
| It's a pretty neat rule to have in mind.
| [deleted]
| dcow wrote:
| It's also good legal advice. It's now legally possible for
| you to copy and paste code directly from stack overflow
| because they made an effort to assert a compatible license
| over works published on their site. However, the same can't
| be said for most other code snippets flying around out there.
| distances wrote:
| Good point in case: license of the code in this exact
| article is very likely incompatible with your production
| code.
| jozvolskyef wrote:
| Ladislav Vagner, a legendary programming tutor at FIT CTU, is
| a known proponent of being extremely cautious when copying
| code, even your own. He gives programming proseminars where
| students guide him as he codes the solution to some problem,
| e.g. mathjax-like typesetting in C++. It is a common theme in
| the proseminars that a bug is introduced by copying code.
| Probably on purpose, like many of the other bugs that
| students are supposed to point out.
| specialist wrote:
| Yes, and:
|
| I didn't really grok Test Driven Development until I worked
| thru the book, line-by-line, experiencing the workflow.
|
| Knowledge vs experience.
| tshaddox wrote:
| I think that's true if you're trying to learn a new tool or
| technology. You probably won't learn as much following the
| Rails or Django tutorials if you're just pasting all the
| code. But if you're just looking for some esoteric workaround
| for some very specific tool and use case, I think it's fine
| to paste. And the latter makes up the overwhelming majority
| of my Stack Overflow visits.
| ImprovedSilence wrote:
| Agreed. Otherwise it's not uncommon for me to not know what
| 80% of the code is even capable of...
| [deleted]
| corobo wrote:
| When you get into this habit it also makes it easier to
| translate solutions from other languages too
| mninm wrote:
| What I realized years ago is that the upvote on Stack Overflow
| don't mean "I tried this and it works for me" or "I'm an expert
| and this is the answer". No, the upvotes on Stack Overflow are
| along the line of the upvotes/likes one would find on Reddit or
| HN. More like "you sound confident" or "I was looking for this
| but I haven't tried it yet"
| sixothree wrote:
| The number of times I've seen the only correct answer being a
| terse explanation with a short code snippet and having zero
| upvotes astounds me.
|
| They may not have been the attention seekers like other
| posters. But they provided exactly what was asked for. And
| when I come across their post years later I upvote.
| ImprovedSilence wrote:
| > More like "you sound confident"
|
| Meh, I'm usually there looking for how to do something, and
| if a response helps me do whatever I was looking to
| acomplish, or at least on the right track, it was helpful and
| worth an upvote. I've never upvoted just because someone
| sounded confident.... at least not on SO.
| keanebean86 wrote:
| There's also the possibility that the answer was correct
| when written. Especially with web stuff a year old answer
| could be completely wrong now.
| MaxBarraclough wrote:
| > No, the upvotes on Stack Overflow are along the line of the
| upvotes/likes one would find on Reddit or HN. More like "you
| sound confident"
|
| I think you're right that online scoring systems tend to
| incentivise false confidence. This happens with blog posts
| too, where a student of some topic writes a confident and
| subtly incorrect blog post, and it then ends up on the HN
| front-page. Only someone with a relatively deep knowledge of
| the topic can then call out the errors. Ideally it should
| always be made clear upfront that the author is new to the
| material.
|
| Somewhat related: Stack Overflow's unfortunate norm of
| calling out mistakes in answers in a way that goes beyond
| confidence and strays into condescension and borderline
| hostility. For a lot of people it seems it's not enough to be
| seen to be right, they also feel the need to paint someone
| else as clueless, while just about passing as acceptably
| polite by keeping the aggression passive. If challenged,
| they'll brush it off as 'directness'.
| kenniskrag wrote:
| Also to create a democracy.
|
| > Our sites are all intended to be a sort of representative
| democracy. Moderator elections are an important part of
| that plan, but voting on questions and answers is the
| primary mechanism through which the community governs the
| site on a day to day basis.
|
| https://stackoverflow.com/help/why-vote
| bombcar wrote:
| And it can fall to all the errors and issues of democracy
| too - especially the "pseudo-expert" one. At least you
| can leave a comment on the answer if there's an issue.
| fouc wrote:
| experts can edit the stackoverflow answers (assuming their
| stackoverflow rating is high enough)
| Nowado wrote:
| It's a user experience issue and it's hard to solve. You
| can't possibly expect people to come back to one of their SO
| tabs AFTER they get code to work.
| nomadiccoder wrote:
| Why not? I dont upvote an answer unless it works...
| luckman212 wrote:
| I think it was sarcasm... just missing the /s
| cratermoon wrote:
| Remember the npm left-pad disaster? That code had bugs in it.
| See slide 44: https://www.slideshare.net/Kevlin/good-
| code-73714882
| OJFord wrote:
| > I also often find on StackExchange et al that quite often the
| most upvoted is the one that 'fixes it' for 'most people'
|
| And also _first_ , or at least early, and subject to a
| reinforcing cycle of 'sufficiently good' or 'fixed it enough'
| that it achieves stratospherically more votes than an 'even
| more good' or 'fixes it properly' answer that came in too late
| for the same traction.
| bigiain wrote:
| > also first, or at least early, and subject to a reinforcing
| cycle of 'sufficiently good' or 'fixed it enough'
|
| So exactly the solution most project managers are after? /s
| OJFord wrote:
| Ha, well even if there's an argument for that, it quite
| often leads to (and is even more reinforced by in terms of
| votes) the original asker 'accepting' the solution; then
| the answer that 'fixed it for them, first' is forever
| ranked highest, even if it rarely works for others and
| something else is more up-voted.
| sixothree wrote:
| This works better when the problem does not 100% match the
| issue you are tackling. It makes you think about how you can
| reshape what you found into something useful.
| AceJohnny2 wrote:
| > _Key Takeaways:_
|
| > _[...]_
|
| > _Floating-point arithmetic is hard._
|
| I have successfully avoided FP code for most of my career. At
| this point, I consider the domain sophisticated enough to be an
| independent skill on someone's resume.
| exporectomy wrote:
| As long as you're using it to represent what could be physical
| measurements of real-valued quantities, it's nearly impossible
| to go wrong. Problems happen when you want stupendous precision
| or human readability.
|
| Numerically unstable algorithms are a problem too but again,
| intuitively so if you think of the numbers as physical
| measurements.
| seoaeu wrote:
| Notably, this is only true of 64-bit floats. Sticking to
| 32-bit floats saves memory and sometimes are faster to
| compute with, but you can absolutely run into precision
| problems with them. When tracking time, you'll only have
| millisecond precision for under 5 hours. When representing
| spacial coordinates, positions on the Earth will only be
| precise to a handful of meters.
| tehjoker wrote:
| Unfortunately, that doesn't work when you have to do:
|
| 1 - quantity2 / (quantity1 - quantity2)
|
| ... or some such thing. If quantity1 and 2 are similar, ouch!
| exporectomy wrote:
| Not sure if there's a mistake in that expression, since if
| they're similar, you're already going to get some
| ridiculously large magnitude (unphysical) result. Maybe you
| mean calculating the error between two values or
| convergence testing? In that case, it hardly matters if
| whether you do
|
| quantity2/quantity1 - 1
|
| or
|
| (quantity2 - quantity1) / quantity1
|
| with double precision and physically reasonable values.
| jrochkind1 wrote:
| Yep, floating point numbers are intended for scientific
| computation on measured values; however many gotchas they
| hsve when used as intended, there are even MORE if you start
| using them for numbers that are NOT that. money or any kind
| of "count" rather than measurement (like, say, a number of
| bytes).
|
| The trouble is that people end up using them for any non-
| integer ("real") numbers. It turns out that in modern times
| scientific calculations with measured values are not
| necessarily the bulk of calculations in actually written
| software.
|
| In the 21st century, i don't think there's any good reason
| for literals like `21.2` to represent IEEE floats instead of
| a non-integer data representation that works more how people
| expect for 'exact' numbers (ie, based on decimal instead of
| binary arithmetic; supporting more significant digits than an
| IEEE float; so-called "BigDecimal"), at the cost of some
| performance that you can usually afford.
|
| And yet, in every language I know, even newer ones, a decimal
| literal represents a float! It's just asking for trouble.
| IEEE float should be the 'special case' requiring special
| syntax or instantiation, a literal like `98.3` should get you
| a BigDecimal!
|
| IEEE floats are a really clever algorithm for a time when
| memory was much more constrained and scientific computing was
| a larger portion of the universe of software. But now they
| ought to be a specialty tool, not the go-to for representing
| non-integer numbers.
| exporectomy wrote:
| I like that idea too. I wonder why Python doesn't use
| bigdecimals by default. Maybe because it seems to require
| you to choose a precision?
| cycomanic wrote:
| I think you are significantly underestimate the prevalence
| of floating point calculations, there is a reason why Intel
| and AMD created all the special simd instructions.
| Multimedia is a big user for example. You also seriously
| underestimate the performance cost of using decimal types,
| we are talking orders of magnitude.
| jrochkind1 wrote:
| Fair! Good point about multimedia/animation/etc.
|
| There are still a lot of people doing a lot of work in
| which they hardly ever want a floating point number but
| end up using it because it's the "obvious" one that
| happens when you just write `4.2`, and the BigDecimal is
| cumbersome to use.
| opheliate wrote:
| So you have problems if you want a precise answer, you want
| to display your answer, or if you want to use any of a large
| number of useful algorithms? That sounds like it's quite easy
| to go wrong.
| exporectomy wrote:
| You can't want a precise answer from physical measurements
| unless you don't know how to measure things. Display should
| be done with libraries, and numerical instability makes
| algorithms basically useless, so you pretty much have to be
| inventing it yourself.
| necheffa wrote:
| I do a lot of floating point math at work and constantly run
| into problems either from someone else's misunderstanding, my
| own misunderstanding, or we just moved to a new
| microarchitecture and CPU dispatch hits a little different
| manifesting itself as rounding error to write off (public
| safety industry).
| exporectomy wrote:
| If you expect bit-for-bit reproducible results, then yea,
| you'd have to know about the nitty-gritty details. The
| values should usually still correspond to the same thing in
| common real world precision though.
| brandmeyer wrote:
| I am regularly reminded of William Kahan's (the godfather of
| IEEE-754 floating point) admonition: A floating-point
| calculation should usually carry twice as many bits in
| intermediate results as the input and output deserve. He
| makes this observation on the basis of having seen many real
| world numerical bugs which are corrupt in half of the carried
| digits.
|
| These bugs are so subtle and so pervasive that its almost
| always cheaper to throw more hardware at the problem than it
| is to hire a numerical analyst. Chances are that you aren't
| clever enough to unit test your way out of them, either.
| RhysU wrote:
| > it's nearly impossible to go wrong
|
| It's a matter of time if one doesn't know to look for
| numerically stable algorithms. Or if one thinks performance
| merits dropping stability.
|
| https://github.com/RhysU/ar/issues/3 was an old saga in that
| vein.
| RhysU wrote:
| Just this week I watched someone discover that computing
| summary statistics in 32-bit on a large dataset is a bad idea.
| The computer science curricula needs to incorporate more
| computational science. It's a shame to charge someone tens of
| thousands of USD and to not warn them that floating point has
| some obvious footcanons.
| bqmjjx0kac wrote:
| Could you shed some light on what they did wrong, and what
| would be a better way to do it?
| cellularmitosis wrote:
| not OP, but the hint is in "computing summary statistics in
| 32-bit on a large dataset".
|
| A large dataset means lots of values, maybe we can assume
| the number of values is way bigger than any individual
| value. Perhaps think of McDonalds purchases nation-wide:
| billions of values but each value is probably less than
| $10.
|
| The simplest summary statistic would be a grand total
| (sum). If you have a good mental model of floats, you
| immediately see the problem!
|
| The mental model of floats which I use is 1) floats are not
| numbers, they are buckets, and 2) as you get further away
| from zero, the buckets get bigger.
|
| So let's say you are calculating the sum, and it is already
| at 1 billion, and the next purchase is $3.57. You take 1
| billion, you add 3.57 to it, and you get... 1 billion. And
| this happens for all of the rest of the purchases as well.
|
| Remember: 1 billion is not a number, it is a bucket, and it
| turns out that when you are that far away from zero, the
| size of the bucket is 64. So 3.57 is simply not big enough
| to reach the next bucket.
| bqmjjx0kac wrote:
| Thanks for the explanation!
| RhysU wrote:
| Well explained! All of the later contributions to the sum
| are effectively ignored or their contributions severely
| damaged in 32-bit because the "buckets" are big.
|
| It was precisely this problem. The individual had done
| _all_ data preparation /normalization in 32-bit because
| the model training used 32-bit on the GPU. It's a very
| reasonable mistake if one hasn't been exposed to floating
| point woes. I was pleased to see that the individual
| ultimately caught it when observing that 2 libraries
| disagreed about the mean.
|
| Computing a 64-bit mean was enough. Compensated (i.e.
| Kahan) summation would have worked too.
| bigiain wrote:
| > Just this week I watched someone discover that computing
| summary statistics in 32-bit on a large dataset is a bad
| idea. The computer science curricula needs to incorporate
| more computational science.
|
| Sadly, I suspect too many "computer science" courses have
| turned into "vocational coding" courses, and now those people
| are computing summary statistics on large datasets in
| Javascript...
| user3939382 wrote:
| There are libraries that offer more appropriate ways of dealing
| with it, but last time I ran into a FP-related bug (something
| to do with parsing xlsx into MySQL) I fixed it quickly by
| converting everything to strings and doing some unholy
| procedure on them. It worked but it wasn't my proudest moment
| as a programmer.
| tomrod wrote:
| I wish to learn a better way. FP is sure to byte again and
| again.
| marcosdumay wrote:
| Well, manually floating the point in a string is sure to
| bite again and again too, but way more frequently than in
| binary.
|
| There is actually no better way, if you try to calculate
| over the reals (with computers or whatever you want), you
| are prone to be bitten. Once in a while there's an article
| about intervalar algebra on HN, those are a great
| opportunity to just nod positively and remember all of the
| flaws of intervalar algebra I got to learn on my school's
| physics labs. (And yeah, those flaws do fit some problems
| better than FP, but not all.)
| rini17 wrote:
| Pity the rational numbers (fractions) did not catch on.
| Of course it has flaws too but bit easier to grasp. And
| it handles important cases like 1/3 or 1/10 exactly.
| pvg wrote:
| _I consider the domain sophisticated enough to be an
| independent skill_
|
| It's been a whole field with its own patron saint for a quite a
| while, take a look at
|
| https://en.wikipedia.org/wiki/William_Kahan
| Torakfirenze wrote:
| Interesting how the same things crop up over time. I remember
| seeing this on HN when it was written in 2019 :)
|
| https://news.ycombinator.com/item?id=21698619
|
| Still, a good lesson!
| deepsun wrote:
| Does Math.log really faster than simple loop with just a couple
| of iterations after JIT compilation?
| cellularmitosis wrote:
| > Granted it's not very readable and log / pow probably makes
| it less efficient than other solutions
| jedimastert wrote:
| Fun fact: The reason Safari/Chrome/Firefox had to freeze the
| MacOS version in the User-Agent string is because of a code-
| snippet from StackOverflow that assumed the version started with
| "10" that snuck its way all over the place, including the Unity
| web player and a major wordpress templete.
| 8bitsrule wrote:
| Overkill. KISS. n counts moving the decimal left 3 places until
| there are <=3 digits left. Keep one place to the right.
|
| "BKMGTPE". n==0 => 'B'; n==4 => 'T'.
|
| 810 has 3 digits. n==0, 810B.
|
| 999950 has 6 digits. n==1, you've got 999.9K
|
| 1100000 has 7 digits. n==2, 1.1M
|
| 1234567890 has 10 digits. n==3, 1.2G
| maest wrote:
| This reminds me of my favourite SO answer:
|
| https://stackoverflow.com/a/40429822/864112
|
| It boggles the mind that anyone could ever suggest this as a
| solution.
| nl wrote:
| You'd think that is so completely wrong that no competent
| programmer would ever do it...
|
| Except the java.net.URL.equals and java.net.URL.hashcode
| methods do almost the same thing: they issue DNS requests (!)
|
| "Two hosts are considered equivalent if both host names can be
| resolved into the same IP addresses; else if either host name
| can't be resolved, the host names must be equal without regard
| to case; or both host names equal to null."
|
| See
| https://docs.oracle.com/en/java/javase/11/docs/api/java.base...
|
| There is a bug raised[1], but it can't be fixed for backwards
| compatibility reasons.
|
| I'll never forget this now, after debugging a very horrible and
| severe and very intermittent performance issue in some code
| over 20 years ago. A (slow) DNS resolver occasionally caused
| 1000x performance degradation on remote sites. That was
| horrible to work out.
|
| [1]
| https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4434494
| [deleted]
| kortex wrote:
| Ew. Yikes. Wow, that's a special kind of special. The mind
| truly boggles. It had a score of 4 when I first checked it, but
| it looks like it got slashdotted by this thread/link and now
| it's -1 and probably still falling.
|
| Good.
| esnard wrote:
| At the time I'm writing this, the answer got 3 upvotes, 13
| downvotes and 1 delete vote since the link has been posted: h
| ttps://stackoverflow.com/posts/40429822/timeline?filter=Wit..
| .
| kortex wrote:
| TIL: that timeline feature is really neat! I don't see a
| way to get to it from the mobile UI though, will need to
| hunt around.
| arduinomancer wrote:
| I'm going to choose to believe that is a joke answer
| cjonas wrote:
| upvoted
| Supermancho wrote:
| I'm intrigued, why? I find multiple places where this is the
| most basic implementation. https://realpython.com/python-
| requests/#query-string-paramet...
| https://www.geeksforgeeks.org/get-post-requests-using-python...
|
| etc
| hvdijk wrote:
| The question was how to build a URL, not how to send off a
| request to it. The answer sends off a request and then
| inspects the response to see what URL was used. If you wanted
| to send off the request, inspecting the URL on the result is
| probably not useful. If you didn't want to send off the
| request, doing it this was is wasteful or even harmful.
| abnry wrote:
| Yes, but unless the answer was edited before the link to HN
| was posted, the user specifically said you should only do
| it if you _really_ intend to make a request, not just
| generate a url. It is conceivable you'd want to log the
| request or something and hence reference the url after the
| request call. Yeah, it is a bad answer to the question as
| stated, but it has a logic to it considering what might be
| the real motivation behind the question.
|
| EDIT: Apparently the answer was edited by another user just
| recently making the clarification.
| Supermancho wrote:
| Interesting, thanks!
| pwdisswordfish8 wrote:
| Your parent poster makes the mistake that is rife among
| Python programmers, which is to assume that in a
| _delightfully simple_ [0] language like Python, it's
| "obvious" what a given piece of code does even without
| explanation. Among people who don't delight in the poor taste
| of Python's design and have limited exposure to its standard
| library, of course, it's _not_ always obvious what a given
| piece of code is doing despite the belief to the contrary, so
| there are plenty of people who aren 't going to pick up on
| the fact that requests.get doesn't just construct a GET
| request for the caller, but instead constructs such a request
| and then goes out and performs it, too.
|
| Shame about the hostile reaction from others towards your
| question. Keep asking questions (especially things that are
| presented without comment), and don't be afraid that doing so
| will make you look stupid or that you should feel like you
| should be punished for it.
|
| 0. https://blog.imgur.com/wp-
| content/uploads/2017/06/mocking.jp...
| JadeNB wrote:
| > Shame about the hostile reaction from others towards your
| question.
|
| I agree that your parent is a good question that should
| have been well received, but, as far as I can tell, it
| _was_. Where do you see a hostile reaction? In fact the
| only hostility I see in this thread is what you directed at
| Python, which, in this context, seems unmotivated; it is
| surely true that one can write code in any language whose
| full import isn 't immediately apparent. At the moment, the
| only other response to your parent is from hvdijk, saying
| (https://news.ycombinator.com/item?id=27534803):
|
| > The question was how to build a URL, not how to send off
| a request to it. The answer sends off a request and then
| inspects the response to see what URL was used. If you
| wanted to send off the request, inspecting the URL on the
| result is probably not useful. If you didn't want to send
| off the request, doing it this was is wasteful or even
| harmful.
|
| This seems like a response that takes the question
| seriously and addresses it clearly, just as it should.
| pwdisswordfish8 wrote:
| At the time I wrote the comment it was clearly _not_
| well-received, and the oblique opening remark from the
| person you 're quoting is _not_ the kind of response that
| addresses the question as it should.
|
| That comment is, just like the downvotes the question
| received, precisely the sort of thing that discourages
| asking honest questions rather than welcoming them. Note
| that by the way it is written it, too, assumes that it is
| both obvious and understood that Python's request.get
| will "send off a request"--instead of merely building a
| request and returning it to you. Rather than just
| straightforwardly answering the question (by explaining
| what this part of the Python' standard library is
| actually doing--which is the relevant missing piece here,
| and which no one should be _expected_ to know) the quoted
| comment ( "The question was how to build a URL, not how
| to send off a request to it") pins the misunderstanding
| on the questioner by tacitly implying the questioner
| isn't paying attention to something else entirely
| different.
|
| The comment, when considered in full and in context,
| _actually_ has the effect of subtly discouraging
| /admonishing the questioner (and likeminded people with
| the same question) for failing to recognize something
| that is, to the sophomoric Python crowd, obvious and
| worthy of ridicule--which is what maest's thread was all
| about, by the way (and almost certainly why it got
| moderated).
| klyrs wrote:
| Wow. Nice comment...
|
| > This is akin to answering "how do I bake a cake?" with "open
| up a bakery, walk inside, and ask for a cake"
|
| Only it's more like answering "how much does this cake cost" by
| purchasing the cake and looking at the receipt.
| TillE wrote:
| Nerds love terrible analogies for some reason, yours is much
| better.
| klyrs wrote:
| An analogy is a high-level abstraction of one domain,
| projected onto a different domain. Of course nerds love
| them.
|
| Or should I say... analogies are like Uber, but for
| metaphors. No. I should stop before writing that.
| throwaway4good wrote:
| Honestly. The code is fine.
|
| This is for presenting stuff in a user interface. Who cares if
| you can find some weird edge case using MAX_LONG and MAX_DOUBLE
| which _never_ will occur in practice.
| Cthulhu_ wrote:
| Until it does.
| throwaway4good wrote:
| Readability and maintainability matters far more.
|
| And no - the edge cannot occur as it would require a file /
| whatever to have that size.
| throwaway4good wrote:
| For example - what is the meaning of the parameter "si"?
|
| I betcha that is going to give you more bugs than the edge
| cases discussed here.
| ayewo wrote:
| The parameter "si" here stands for International System
| of Units, or SI for short [0].
|
| 0: https://en.wikipedia.org/wiki/International_System_of_
| Units#...
| moring wrote:
| The original doesn't have types, but the modified version of
| humanReadableByteCount() uses a "long bytes" and as such will
| fail if the file size is (Long.MAX_VALUE+1) because it cannot
| even accept the correct size as its argument in the first
| place. Implementing these edge cases makes adds one more
| working case to 2^63 (2^64 if negative file sizes are valid)
| when the bigger problem is using the type "long" when files
| of that size are possible on the target system.
| cratermoon wrote:
| Reminds me of this article on roman numerals
| https://kevlinhenney.medium.com/out-of-control-97ed6efa2818
| williesleg wrote:
| China bots
| tasty_freeze wrote:
| The thing that jumped out at me, as I've seen the same kind of
| thing on the job, is the assumption that, eg, log(1000)/log(10)
| is _exactly_ 3. Does the standard guarantee that the rounded
| approximation of one transcendental number by the rounded
| approximation of a related transcendental number will give 3.0
| and not 2.999999999?
| remram wrote:
| Yeah that seems like a serious flaw to me too. On my Python:
| >>> math.log(1000)/math.log(10) 2.9999999999999996
| >>> int(math.log(1000)/math.log(10)) 2
|
| But I don't know about the guarantees provided in the
| JavaScript standard (or more importantly those offered by
| actual browsers).
| halter73 wrote:
| Floating point math is IEEE 754 in pretty much all cases, so
| you should see this result in most languages. `math.log(1000,
| 10)` gives the same result because it's implemented using
| natural logs internally as it is in most languages.
|
| In this case, there's only about six boundary cases to
| consider so you can just manually verify it works as
| expected.
| danellis wrote:
| > almost no branches
|
| I wonder whether the author is suggesting that (potentially) nine
| branches is a small number, or they overlooked ternary
| expressions and function calls and are just counting the if
| statement.
| TwoBit wrote:
| There are tons of branches in those log and pow calls.
| Programmers are lost in branch free religion.
| Tempest1981 wrote:
| Shows how much people enjoy writing code (puzzle solving) and
| hate writing unit tests.
| bombcar wrote:
| It seems to me that the elegant solution would involve an
| instruction that returns the first non-zero bit of the number -
| but I don't know if such a instruction exists in assembly.
| muricula wrote:
| Basically lzcnt or leading zero count on x86:
| https://www.felixcloutier.com/x86/lzcnt
| ac42 wrote:
| > It should be noted that on processors that do not support
| LZCNT, the instruction byte encoding is executed as BSR.
|
| This. Boggles.
| bombcar wrote:
| https://stackoverflow.com/a/43443701 - interesting - it
| seems to be a side effect of changing meaning of an
| instruction.
| [deleted]
| jasonhansel wrote:
| IMHO any code that tries to perform floating-point arithmetic on
| integer values and then produce exact output should be considered
| suspect in and of itself...too many edge cases.
| axiosgunnar wrote:
| So it's not flawed (it does compute the correct result).
|
| The author just thinks a completely unreadable (but supposedly
| faster) variant using logarithms is "better" than the simple loop
| used in the original snippet?
|
| Write your code for junior devs in their first week at your
| company, not for academic journals.
| lucideer wrote:
| Sibling commenters have already pointed out that you seem to
| have misread the post, but tbh I found it quite confusing to
| follow myslf, so here's a summary:
|
| - the first answer posted on SO was a simple loop
|
| - the author posted a 2nd (supposedly faster but less readable)
| answer. The author didn't think this answer was _better_ than
| the loop, but it seems the community did and it became accepted
| (and extremely popular). THIS is the version that was buggy.
|
| The author later went back and fixed their own buggy version.
|
| So yes there's an argument to be made that the very first
| simple loop was better, but that's orthogonal to the point of
| the story.
| klyrs wrote:
| > Write your code for junior devs in their first week at your
| company, not for academic journals.
|
| Hard and fast rules about coding style are silly. There's a
| time and place for clever code, and there's a time and place
| for verbose and straightforward code.
|
| I write performance-critical code. Juniors shouldn't be mucking
| about there, because it's performance critical. I also write
| non-performance-critical code with some effort. I write that
| stuff for the juniors.
|
| When writing for academic journals, it looks like the stuff I
| write for juniors. I'll drop a hint here or there so experts
| can reproduce less-obvious optimizations.
| pseudosavant wrote:
| He ends the blog post with this: "Personally I would not copy
| this snippet into production code."
|
| He isn't trying to get people to use the log version.
| arduinomancer wrote:
| Can you please read the article all the way before commenting
| next time?
|
| The log approach _is_ the most copied snippet.
| hardwaregeek wrote:
| I think you might have misread the post. His logarithm code
| became the most used snippet and had the bug.
| [deleted]
| [deleted]
| [deleted]
| ascar wrote:
| His code snippet had rounding errors on the boundaries towards
| the next unit.
|
| However he notes:
|
| > FWIW, all 22 answers posted, including the ones using Apache
| Commons and Android libraries, had this bug (or a variation of
| it) at the time of writing this article.
| phist_mcgee wrote:
| You should almost _always_ focus on code readability and
| simplicity over inventiveness and cleverness.
|
| Very few people I have encountered have complained about code
| being 'too simple' or 'too readable', but the opposite happens
| on a near daily/weekly basis.
|
| Write comments, use a for loop, avoid global state, keep your
| nesting limited to 2-3 levels, be kind to your junior devs.
| djur wrote:
| What does "use a for loop" mean here? Aren't for loops
| infamously difficult for new programmers to understand?
| GuuD wrote:
| I think I successfully avoided writing for loops in
| application code for the last 3 years. I don't miss them.
| foysaluix wrote:
| At the very least, the loop based code could be cleaned up
| significantly.
| ddlatham wrote:
| I'm the author of #6 on the same list. It's definitely
| interesting to see it has been used thousands of times on GitHub,
| and who knows how many more in proprietary code. I don't think
| it's buggy, but I now think it could definitely be improved.
|
| I think this shows an example of a big problem with StackOverflow
| compared to its initial vision. I remember listening to Jeff and
| Joel's podcast, and hearing the vision of applying the Wikipedia
| model to tech Q&A. The idea was that answers would continue to
| improve over time.
|
| For the most part, they don't. I'm not quite sure if it's an
| issue of incentives or culture. Probably some of both. I think
| that having a person's name attached to their answer, along with
| a visible score really gives a sense of ownership. As a result,
| other people don't feel enabled to come along and tweak the
| answer to improve it.
|
| Then, once an answer is listed at the top, it is given more
| opportunity for upvotes, so other improved answers don't seem to
| bubble up. This is a larger issue with most websites that sort by
| ratings. Generally they sort items based on the total number of
| votes, including hacker news itself. Instead, to measure the
| quality of an item, we should look at the number of votes,
| _divided by the number of views_. It may be tough to measure the
| number of views of an item, but we should be able to get a rough
| estimate based on the position on a page, for example.
|
| If the top comment on a HN discussion is getting 100 views in a
| minute and 10 upvotes, but the 10th comment down gets 20 views
| and 5 upvotes, the 10th comment is likely a better quality
| comment. It should be sorted above the top ranked comment! There
| would still need to be some smoothing and promotion of new
| comments to get them enough views to measure their quality as
| well.
|
| Such a policy on StackOverflow would also help newer, but better
| answers sort to the top.
| L_226 wrote:
| Potentially a stupid question; why is it not possible to just
| make a MediaWiki site explicitly for SO questions? Does it
| exist already?
| fragmede wrote:
| The technical cost/effort for someone like you or me to do
| that is minimal. The expensive part is the ongoing social
| maintenance fee aka moderation. As evident by the stack
| overflow drama re: Monica, it's an unsolved (non-technical)
| problem that you could make your own mint to print money on,
| if you were able to fix any tiny part of it.
| BrandoElFollito wrote:
| And then we would run again into people with an inflated
| ego, edit wars etc.
| wizzwizz4 wrote:
| The Monica situation is probably a bad example; that was
| Stack Overflow (the company) royally and unilaterally
| messing up. It's certainly not a usual situation for
| resource-curating communities.
|
| I've written, and deleted, several essays on the matter,
| but a TL;DR: Monica's legitimate questions to staff about a
| policy got caught up in a crackdown on sealioning-type
| harassment of trans (etc.) mods in the mod chat, and SO
| management basically declared war on Monica by mistake. We
| don't know whether they dealt with the _actual_ harassment
| (though I think they did, belatedly), because if they did,
| proper procedure was followed and the perps weren 't named-
| and-shamed in the press.
| lkrubner wrote:
| To correctly measure the quality of an item one needs to take
| something like Google's PageRank algorithm and apply it to
| people. That is, there needs to be some measure of the
| reputation of the person posting. This doesn't mean that a
| person who was correct in the past is necessarily correct right
| now, but it is true that people who are often correct tend to
| go on being correct, and people who are often wrong tend to go
| on being wrong. Careful people tend to continue to be careful,
| and sloppy people tend to continue to be sloppy. It's important
| to capture that reality and use it as a weight given to any
| particular answer.
| cerved wrote:
| I always try and improve existing answers with edits. Often
| just adding important context when the answer is just a line of
| bash and adding links to source documentation.
|
| There's very little gamification incentive to do so and often
| the edit queue is full. Still, there are lots of times where
| important caveats and information is pointed out in the
| comments and never added to the answer
| ant6n wrote:
| The other day I asked a question about the c/c++ plugin of
| vscode, somebody swooped in to edit it to just be c++ because
| "c/c++ is not a programming language". The question wasn't
| answered. I wonder what's the incentive for people to do
| something like that.
| shkkmo wrote:
| > As a result, other people don't feel enabled to come along
| and tweak the answer to improve it.
|
| It's worse than that. Edits have to go through a review process
| that is much more selective and often arbirarily rejects good
| edits.
| matsemann wrote:
| Only if you're a low rep user, though. And no, many more bad
| edits are accepted, than good edits being rejected. By orders
| of magnitude.
| shkkmo wrote:
| > Only if you're a low rep user, though.
|
| What qualifies as "low rep"? I'm easily in the too
| quintile.
|
| > And no, many more bad edits are accepted, than good edits
| being rejected. By orders of magnitude.
|
| Do you have any data to support this?
|
| The editing and updating process for stackoverflow is
| broken and as a direct result I've used the site less and
| less over the years. Denying the problem just hastens the
| demise of the site.
| bachmeier wrote:
| Editing answers is a complete waste of time. You can post a
| correction along with a copy and paste of the relevant
| section from the documentation, yet have your edit disappear
| without explanation.
| rcthompson wrote:
| One of the really frustrating things about SO is that once you
| reach a certain rep threshold, you _lose_ the ability to
| suggest edits, and instead gain the ability to just make the
| edits directly. I 'm a _lot_ more likely to do the former,
| because it helps ensure that if I actually made a mistake, it
| will be caught by the people voting on it. And so SO has lost
| out on a bunch of my suggested edits because they took away my
| ability to suggest edits.
| macksd wrote:
| >> For the most part, they don't. I'm not quite sure if it's an
| issue of incentives or culture.
|
| Classic example of "good is the enemy of best".
| ayewo wrote:
| For anyone else that is curious like I was, the #6 answer on
| that list is from 12 years ago:
| https://stackoverflow.com/a/140861/
| slightwinder wrote:
| > I think this shows an example of a big problem with
| StackOverflow compared to its initial vision. I remember
| listening to Jeff and Joel's podcast, and hearing the vision of
| applying the Wikipedia model to tech Q&A. The idea was that
| answers would continue to improve over time.
|
| Interessting. As a random visitor this was something that never
| came to me from the way SO presents itself.
|
| > For the most part, they don't. I'm not quite sure if it's an
| issue of incentives or culture.
|
| I think it's more a problem of communication and UI. SO is not
| really the kind of site that animates people to answer or
| improve things. The overall design is also more technical and
| strange, not motivating and userfriendly.
|
| Today for the first time I realized that there is a history for
| answers and an "improve"-Button that seems to allow me to
| change someone else answer. I only saw that because I expliciet
| looked for this because of this thread.
|
| Wikipedia in the beginning was very vocal and motivating to
| engage all kind people to help and improve articles. SO never
| had that vibes for me. Additionally, it simply has not the
| interface that makes it simple to do this stuff. There are only
| this aweful comments under each answer, which are not really
| useful to discus an answer in all lenght and from all sides.
| Might be better to change them to a full fletched forum with
| some kollaboration editing and some small wiki-functionality or
| something like that.
|
| I remember they tried to do some kind of wiki with high
| quality-code-parts, what happend to that?
| saganus wrote:
| One of the things that baffles me the most about SO is that I
| can't sort answers by _newest first_.
|
| If I search for something related to javascript for example, I
| know there will be a ton of answers for older versions that I
| am most likely not interested in. However I can only sort by
| oldest first (related to date).
|
| Old answers are definitely useful a lot of times, but the fact
| that there's not even the option to sort them the other way
| around tells me that SO somehow, at it's core, considers new
| answers less important.
|
| A strange decision if you ask me, considering software changes
| so much over time.
|
| If anyone has a possible explanation for this I'd love to hear
| it.
| bachmeier wrote:
| > If I search for something related to javascript for example
|
| As someone that's been learning a little JS over the last
| year, I quickly came to the realization that you skip over
| the SO links that come up in the search, and you go to one of
| the many other sites. I've had good luck with w3schools and
| mdn. SO is a lost cause for JS.
| saganus wrote:
| I agree.
|
| However sometimes I am looking for some error related to a
| botched nodejs install for example, or something that has
| to do with permissions being set incorrectly and other
| stuff that does not live in MDN and other documentation
| sources.
|
| For the actual language questions I do go directly to MDN
| instead.
| acomjean wrote:
| I always thought the should have a language version. Eg
| python3, php7. JavaScript es6....
| Cthulhu_ wrote:
| Tags work to categorize by language
| (https://stackoverflow.com/questions/tagged/python-3.x); by
| having multiple languages on one site, you'll have a
| broader audience because there's few developers that only
| work with one singular language.
| apnorton wrote:
| There are three buttons that act as sorting directions at the
| top of the answers section: "Votes," "Oldest," and "Active."
| The "Active" option sorts by most recently modified, which is
| _usually_ what you'd want instead of strictly newest. (i.e.
| an edit would update the timestamp, making that answer have a
| more recent activity date)
|
| So, I guess the answer to your question of "why can't I" is
| "good news! you can" :)
| saganus wrote:
| Well, none of those options do what I want.
|
| More often than not, sorting by "Active", "Oldest" and
| "Votes" usually surface the same 2 or 3 answers, and I
| still need to scroll down to the bottom to find out the
| most recently posted answer that has more up to date info.
|
| I don't see why I shouldn't have the choice to sort by
| "Reverse Oldest" if you will, when it's so useful a lot of
| the time.
| ooOOoo wrote:
| This is why Stack Overflow has just started the "Outdated
| Answers project" in which users can set answers as outdated:
| https://meta.stackoverflow.com/questions/405302/introducing-.
| ..
| analyte123 wrote:
| What would really help with the vision here is some way to
| comment and associate tests against posted code. I have
| corrected algorithms on Wikipedia that were obviously wrong
| with even a cursory test. Then people can adjust the snippet,
| debate the test parameters, or whatever else they need to do
| while maintaining some sort of sanity check. If it's good
| enough for random software projects used by a dozen people,
| it's probably good enough for snippets used by thousands of
| developers and even more users.
| travisjungroth wrote:
| This post made me think the same thing. It would be nice to
| have a StackOverflow that was actually more code focused.
| People could write tests or code and actually run them.
| hansvm wrote:
| > we should look at the number of votes, divided by the number
| of views
|
| Closer, but still not quite what you want probably or a few
| stray votes can make a massive impact just from discretization
| effects. What you really care about is which answer is "best"
| by some metric, and you're trying to infer that as best as
| possible from the voting history. Average votes do a poor job.
| Check out this overview from the interblags [0].
|
| [0] https://www.evanmiller.org/how-not-to-sort-by-average-
| rating...
| Matumio wrote:
| This isn't just a statistical problem, it's also a classical
| exploration/exploitation trade-off. You want users to notice
| and vote on new answers (exploration), but users only want to
| see the best answers (exploitation). The order you show will
| influence future votes (and future answers).
|
| In addition, it's a social engineering problem. At least
| people with a western psychology seem to respond very
| strongly when a score is attributed to their person (as
| opposed to a group success like in a wiki). So you better
| make the score personal and big and visible, and do not
| occasionally sort by random just to discover the true score.
| ddlatham wrote:
| I think that's a great example of the "smoothing" that I was
| alluding to, though not in a format accessible to most
| programmers. However it is still just using a function of
| upvotes and downvotes. I think true rating can be much better
| when you also incorporate number of _opportunities_ to vote.
| Because having the opportunity to vote (by viewing an item,
| or purchasing it, or whatnot) and choosing not to vote is
| still a really useful piece of data about the quality of an
| item. Especially when you are comparing old items that have
| had millions of opportunities against new items with only
| thousands.
| hansvm wrote:
| > number of opportunities
|
| Yep, definitely. The only challenges there are that there's
| less literature about doing so and that if you have both up
| and down votes there's no longer one right way to define a
| single objective for scoring.
| jsmeaton wrote:
| An idea I've had for a long time is that "the community" can
| vote to override an accepted answer. There are many times when
| the accepted answer is incorrect, or a newer answer is now more
| correct, but the only person who can change an accepted answer
| is the OP.
|
| I think community-based changes to the accepted answer would go
| a long way to solving your problem too, but it requires someone
| to be reviewing newer answers and identifying when there's
| another that would be more appropriate.
|
| It'd incentivise writing newer answers to older questions.
| Correcting accepted answers that probably weren't ideal to
| begin with. A new "role" where users hunt through older
| questions and answers looking for improvements to make.
|
| Stack Overflow answers are supposed to be community-based, but
| we unfairly prioritise the will of the original questioner
| *forever*. I don't think that's optimal.
| weinzierl wrote:
| _" An idea I've had for a long time is that "the community"
| can vote to override an accepted answer."_
|
| I don't know if this is still a thing, but for some time in
| the past when an answer was edited more than a certain amount
| of times it automatically turned into what was called a _"
| community wiki"_ answer.
| inglor wrote:
| They actually recently added this feature - you have a "this
| answer is outdated" button you can press. Note sure what the
| reputation threshold to see it is.
| dotancohen wrote:
| > but the only person who can change an accepted answer is
| the OP.
|
| This system makes the person arguably _least qualified_ to
| understand the situation the single arbitrator as to which
| answer is accepted.
|
| Was it the most efficient? First to answer? Copied-and-pasted
| right in with no integration work? Written by someone with an
| Indian username? Got the most upvotes? Made a Simpsons
| reference? Written by someone with an Anime avatar?
| NaturalPhallacy wrote:
| > _This system makes the person arguably _least qualified_
| to understand the situation the single arbitrator as to
| which answer is accepted._
|
| Devil's advocate: If it fixed their problem adequately,
| it's acceptable.
|
| Maybe separate "acceptable" and "ideal" answers would be a
| nice feature?
| dotancohen wrote:
| In the vast majority of cases, OP did not check (or even
| define) edge cases, race conditions, memory usage,
| network activity, etc etc etc.
| aweiland wrote:
| Seems like the answer is to add a community accepted answer
| that's easier to change over time, while keeping the
| accepted answer feature as is.
| passivate wrote:
| >This system makes the person arguably _least qualified_ to
| understand the situation the single arbitrator as to which
| answer is accepted.
|
| What is the argument for the OP being the least qualified?
| dotancohen wrote:
| Of all the people involved, he was the one who _didn't_
| know how to resolve a specific issue.
| passivate wrote:
| Well, they do know the tech stack, the domain, the
| specific problem. Now they know whether the solution
| resolved their specific problem, if their code
| review/testing caught any bugs, etc, etc.
|
| If anything, they have the most amount of information in
| this context. I really don't think of them as being the
| least qualified.
| Leherenn wrote:
| The argument is probably that while they are the best
| qualified to know whether it solved their issue, they're
| not qualified about whether it was the best way to solve
| their issue, since they had to ask in the first place.
| zatkin wrote:
| Or you could just edit the accepted answer if it's wrong?
| I've seen a few posts where the top contains an "UPDATE"
| that, in summary, links to another answer.
| irrational wrote:
| As a side gig I teach an intro to web development class
| online. Every semester I get students asking for help about
| why their code isn't working. Nine times out of ten, they are
| trying to use some jQuery code they copied from stackoverflow
| because it is the accepted answer. They don't yet know enough
| to recognize that it isn't vanilla JavaScript (which they are
| required to use).
| dotancohen wrote:
| The best way to address these students is to ask them "Why
| do you think that this should work?"
| jka wrote:
| There might be an opportunity somewhere around this area to
| combine the versioning, continuous improvement, and dependency
| management of package repositories with the Q&A format of
| StackOverflow.
|
| Something like "cherry pick this answer, with attribution, and
| notifications when flaws and/or improvements are found".
|
| Maybe that's a terrible idea (there's definitely risk involved,
| and the potential to spread and create bad software), but equally
| I don't know why it would be significantly worse than
| unattributed code snippets and trends towards single-function
| libraries.
| fennecfoxen wrote:
| NodeJS did something a lot like this by having packages that
| are just short snippets, but half the ecosystem flipped out
| when someone messed up `leftpad`.
| fastball wrote:
| Well that and because having 20,000 packages in your project
| is a PITA in various ways.
|
| Mostly but not entirely because NPM handled things poorly in
| various ways.
| [deleted]
| Smithalicious wrote:
| Sadly updates don't just remove bugs, but sometimes also add
| them. Silently adding a bug to previously working code is a lot
| more bad than silently fixing a bug you didn't know you had is
| good, so I wouldn't want to have a load of self-updating code
| snippets in my codebase.
| DylanSp wrote:
| Not sure if it's quite what you had in mind, but SO is starting
| to address the issue of updating old answers with the Outdated
| Answers Project:
| https://meta.stackoverflow.com/questions/405302/introducing-...
| jka wrote:
| Very relevant, thank you!
| pkaye wrote:
| Now the new code is unreadable.
| ape4 wrote:
| Its as easy as "KMGTPE"
| dathinab wrote:
| This specific example is a good example why you should keep code
| as simple as possible, and why even "simple" math needs special
| care when testing (Because floats are not simple.)
| cottsak wrote:
| is it reasonable to assume a strong correlation between "copied
| code" and number of upvotes? #trolling #kiddingnotkidding
| [deleted]
| zgs wrote:
| The proposed solution is crazy. Logarithms are extremely
| expensive to compute. No way is this code more efficient than the
| loop it "replaced".
|
| That there then are numeric stability issues and a pretty gross
| fudge factor is used to fix them worsens the situation. I would
| have a quiet word with any programmer I worked with that came up
| with this "solution".
| [deleted]
| penteract wrote:
| This is a bit of a tangent, but while it may be conventional to
| round to the value with the smallest difference, is that
| convention good? In a case such as this where it's fine for the
| prescision to vary with magnitude, then I'd argue it makes sense
| to round to the value with the smallest ratio.
| kylejrp wrote:
| As part of the Stack Overflow April Fools' prank, we did some
| data analysis on copy behavior on the site [0]. The most copied
| answer during the collection period (~1 month) was "How to
| iterate over rows in a DataFrame in Pandas" [1], receiving 11k
| copies!
|
| [0] https://stackoverflow.blog/2021/04/19/how-often-do-people-
| ac...
|
| [1] https://stackoverflow.com/a/16476974/16476924
| audiometry wrote:
| That's sad, as when you find yourself iterating over rows in
| pandas you're almost invariably doing some wrong or very very
| sub optimally.
| arnaudsm wrote:
| I'm glad that DataFrames don't iterate by default. It's good
| design to make suboptimal features hard to access.
| dannyw wrote:
| To me it's an means to an end. I don't care if my solution
| takes 100ms instead of 1ms, it's the superior choice for me
| if it takes me 1 minute to do it instead of 10 minutes to
| learn something new.
| bruce343434 wrote:
| The flaw of human nature on display. And I don't mean that
| personal, not to you anyway, but to the human species.
| coopsmoss wrote:
| Why? It seems very rational. Especially if you're just
| going to run it once to get a value and not as a part of
| some system.
| kamray23 wrote:
| Exactly, that's not a flaw, that's rational behaviour.
| Why design an intricate solution for a one-off. Using 15
| times the amount of time it would have taken you manually
| to automate a pretty standard task is just stupid, though
| we all do it.
|
| Do the first thing that works, don't overthink it.
| bruce343434 wrote:
| Why learn anything at all then? Why bother learning OOP
| paradigms if procedural just works? Why bother ...? Do
| you see the flaw in your argument?
| wruza wrote:
| One doesn't learn rock climbing to step over a brick,
| man.
| passivate wrote:
| I think the flaw is you misinterpreting the argument.
|
| In my opinion, the bottom line with obvious caveats is
| this - Human-time is more valuable than CPU-time.
|
| If you are shipping at scale then the calculus is
| different - Don't waste end-users' human-time and their
| cpu-time and/or server's cpu-time.
|
| If you're writing code with a team the calculus is
| different - Use/Learn techniques and tools to reduce the
| teams' human-time wastage plus all the above.
|
| If you're writing code just for yourself the calculus is
| different - Save your own human-time.
| dizzy3gg wrote:
| Because when it's not a one off?
| laumars wrote:
| If that was a fair comment then we'd be writing all our
| code in assembly still.
| BrandoElFollito wrote:
| True, but sometimes these 10 minutes help you to discover
| something new that will improve your code.
|
| I had a few of these cases in my life:
|
| - discovering optimized patterns in Perl, which led to code
| I could not understand the next day
|
| - discovering decorators in Python, which led to better
| code
|
| - discovering comprehensions in Python (a magical thing)
| that led to better code, except when I wanted to be too
| clever and ended up with Perl-like code
| NaturalPhallacy wrote:
| >That's sad, as when you find yourself iterating over rows in
| pandas you're almost invariably doing some wrong or very very
| sub optimally.
|
| Humans writing code is suboptimal. I can't wait for the day
| when robots/AI do it for us. I just hope it leads to a utopia
| and not a dystopia.
| tgb wrote:
| I iterate over rows in pandas fairly often for plotting
| purposes. Anytime I want to draw something more complicated
| than a single point for each row, I find it's simple and
| straight-forward to just iterrows() and call the appropriate
| matplotlib functions for each. It does mean some plots that
| are conceptually pretty simple end up taking ~5 seconds to
| draw, but I don't mind. Is there really a better alternative
| that isn't super complicated? Keep in mind that I frequently
| change my mind about what I'm plotting, so simple code is
| really good (it's usually easier to modify) even if it's a
| little slower.
| bla3 wrote:
| > At the very least, the loop based code could be cleaned up
| significantly.
|
| Seems like the loop based code wasn't so bad after all...
| meetups323 wrote:
| Loop code has the same bug.
| bla3 wrote:
| This is Java, not JavaScript. The exponents table was likely
| of integer type. Then it works.
| alisonkisk wrote:
| How does that avoid the misrounding bug for 999,999B =
| 1000KB (wrong), 1MB correct?
| bla3 wrote:
| D'oh, you're right.
| spkm wrote:
| This! If I had to choose between the two snippets I would have
| taken the loop based one without a second though, because of
| its simplicity. The second snippet is what usually happens when
| people try to write "clever" code.
| bigiain wrote:
| In his defences, he did admit at the start of the blog post
| that he was code golfing.
| dataflow wrote:
| The loop by itself isn't entirely clear on what it's doing.
| Stuff like the direction of the > comparison and what to do
| vs. >= and the byteCount / magnitudes[i] at the end really do
| require you to pause & do mental analysis to check
| correctness. I think the real solution here is to define an
| integer log (ilog()?) function based on division and use that
| in the same manner as the log(). That way you only do do the
| analysis the first time you write that function, and after
| that you just call the function knowing that it's correct.
| jmelloy wrote:
| I was reading this and thought it sounded familiar. A few
| months ago I needed a human readable bytes format, ended up
| on that stack overflow article and, plot twist, copied the
| while loop one.
| twobitshifter wrote:
| Premature optimization strikes again.
| Smithalicious wrote:
| I don't think this works very well as a cautionary tale because
| honestly, I would not even care about a bug like this. It's
| something very few people would even figure out exists at all,
| it's incredibly inconsequential.
| cellularmitosis wrote:
| You've made a judgement call that correctness isn't a priority
| in this circumstance, and as long as your judgement is sound,
| this approach will serve you well.
|
| The weakness of your approach is that no one's judgment is
| sound 100% of the time.
|
| Alternatively, folks who always prioritize correctness may
| occasionally "waste their time", but two things to consider: 1)
| their judgement is no longer an issue, and 2) in the long run
| they have spent more time training their correctness muscles
| and are in better shape.
| wongarsu wrote:
| However this "bug" is still entirely within spec. The whole
| article hinges on "the 1,000 "significand" is out of range
| according to spec", but it really isn't. 999999 Bytes are
| indeed around 1000kB. Sure, calling it 1MB would be
| preferable, but saying 1000kB doesn't violate any rule, is
| perfectly acceptable according to SI (just like I can say
| 1000g or 1kg interchangeably), fulfills the task of being
| human readable, and in all the examples given in the task the
| code behaves as requested.
|
| Sure, the code doesn't do exactly what the programmer wanted.
| But that doesn't necessarily make it incorrect.
| amelius wrote:
| Wouldn't it be cool if you could call stack overflow answers
| directly from your code?
| tscherno wrote:
| https://github.com/BrandonShar/stack-overflow-buddy
| xqk8 wrote:
| You can, it's called NPM
| leephillips wrote:
| What sticks out for me is that people don't even rename functions
| when copypasting from SO.
| sgarman wrote:
| I know everyone is on their high horse about copying code but
| if you were/are to copy code keeping it the same is super
| valuable because invertible when someone comes a long later
| googling it will take them to where it was copied from
| originally.
| kalleboo wrote:
| When I'm "inspired" by code from somewhere, I go ahead and
| put the URL in there in a comment
| ChrisArchitect wrote:
| previous discussion:
| https://news.ycombinator.com/item?id=21698619
| code_duck wrote:
| My top Stack Overflow answer of all time is a now rather dated
| two lines of JavaScript: how to tell if a variable is undefined.
| I posted this in 2010 and have been getting points for it
| steadily for a decade, now exceeding the amount I garnered from
| all other activities while actively using the site. I don't do js
| anymore but from what I understand the answer hasn't been
| accurate since 2016 or something.
| hardwaregeek wrote:
| Floating point is really really hard to get right, especially if
| you want the numbers to be stable. Which begs the question, why
| the heck does JavaScript, the most used language in the world,
| not have an integer type? Sure, there's BigInt but that's quite
| clunky to use. I know it's virtually impossible to add by now,
| but I'd love a integer type for all my bit twiddling, byte
| munching needs.
| ascar wrote:
| I just feel if you have bit twiddling, byte munching needs
| JavaScript shouldn't be the language of choice. Doing that is a
| rather rare edge case and if you're doing it for performance
| reasons, working in Javascript is the much bigger performance
| problem.
| hardwaregeek wrote:
| That may be true but another case where floating point should
| be avoided is with money. Now think about all the times a web
| developer innocuously used a JS number to represent a price.
| I wouldn't be surprised if floating point errors affected
| billions of dollars of transactions.
| btilly wrote:
| If you're already using JavaScript for some other reasons but
| occasionally have bit twiddling, byte munching needs, then
| trying to do that in JavaScript makes perfect sense. Is it
| the fastest option? No. But according to
| https://benchmarksgame-
| team.pages.debian.net/benchmarksgame/... it is generally
| within a factor of 4-5 of C++.
|
| For an application area where this applies, consider a web-
| based game. Using JavaScript keeps you from shipping another
| application. But occasionally you may have bit twiddling
| and/or byte munching needs. Which you need to do in
| JavaScript.
| ascar wrote:
| My point wasn't to say you should never do byte
| manipulation in Javascript, but that for these rare edge
| cases the existing capabilities without a native int are
| fine and if you would really need the native int rather
| than some equivalent work around (which I assume is most
| likely due to performance considerations) a faster language
| is the better approach. A webgame might be able to use wasm
| for that.
| lilyball wrote:
| When the author started introducing all the calculations to
| figure out if the printed version would round up, my first
| thought was, why not just look at the printed version? Print it
| as %.1f, then chop off anything past the period and re-parse it
| as an integer. Now you can trivially tell if it rounded up past
| the threshold and you need to bump the suffix.
| colejohnson66 wrote:
| What's wrong with a simple loop (like the one near the top)? Why
| does it _have_ to branchless? Wouldn't the IO take longer than
| missed branches /pipeline flushes?
|
| Not to mention that the fixed version now has branches as well...
| MauranKilom wrote:
| The irony is that a single log computation is going to take
| longer than the loop. (No idea if implementing a log
| approximation involves loops either.)
| [deleted]
| bottled_poe wrote:
| Sounds like textbook example of when theory is misaligned
| with reality.
| slavik81 wrote:
| https://code.woboq.org/userspace/glibc/sysdeps/ieee754/dbl-6.
| ..
|
| I don't see any loops, but there are a number of branches.
| The code could probably be generalized using loops to support
| arbitrary precision, but I think any optimized implementation
| for a specific precision will have unrolled them.
| kortex wrote:
| Waiting for someone to post some fast-inverse-sqrt-esque hack
| to compute the logarithm. Although in Java that's probably
| not likely to be faster.
|
| I wonder how fast it'd be to convert to string and count
| digits.
| Gibbon1 wrote:
| > I wonder how fast it'd be to convert to string and count
| digits.
|
| When you convert the number to a string you're really
| transforming it to a decimal format. Which is the domain
| where you should be solving the problem. Otherwise you're
| doing some sort transformation in the binary domain and
| then hopping to pull the answer out of a hat when you do
| the final convertion to decimal.
| tzs wrote:
| Many architectures include a logarithm instruction. Does Java
| use that if available? Would it make a difference?
| usr1106 wrote:
| Many architectures? What would they be?
|
| Regardless whether they contain a logarithm instruction or
| not, how may architectures are there these days. Outside of
| truly embedded computing I can only come up with 2: Intel
| and ARM. Counting POWER and RISCV is probably a bit of a
| stretch already.
| tzs wrote:
| x86 has two logarithm instructions, FYL2X and FYL2XP1.
|
| FYL2X takes two arguments, Y and X, and computes Y
| log2(X).
|
| FYL2XP1 takes two arguments, Y and X, and computes Y
| log2(X+1).
|
| As you note, x86 and ARM are by far the most used, and
| I'd guess that when it comes to Java you are more likely
| to be running on x86 than ARM, so I figured it was
| arguable to say "many" when the only one I was sure had a
| logarithm instruction was x86.
| colejohnson66 wrote:
| Those x86 instructions are "legacy floating point"
| instructions. As in, the x87 FPU. Benchmarks I've seen
| seem to indicate that the x87 "coprocessor" is slow
| compared to the SSE/AVX FPUs, and only exists for
| backwards compatibility. I don't think SSE/AVX has a
| logarithm instruction, sadly, but there are intrinsics
| for them: `_mm256_log_pd` for example. Considering that
| intrinsic generates a "sequence" instead of a single
| instruction, I'd be curious how it compares to x87.
| xxpor wrote:
| the original version had branches too, in fact a majority of
| the lines had them! ? is just shorthand for if.
| enedil wrote:
| This isn't true, this form of conditionals can be compiled
| into cmov type of instructions, which is faster than regular
| jump if condition.
| dataflow wrote:
| > This isn't true, this form of conditionals can be
| compiled into cmov type of instructions, which is faster
| than regular jump if condition.
|
| IIRC cmov is actually quite slow. It's just faster than an
| unpredictable branch. Most branches have predictability so
| you generally don't want a cmov.
|
| Speaking of which, a couple questions regarding this for
| anyone who might know:
|
| 1. Can you disable cmov on x64 on _any_ compiler? How?
|
| 2. _Why_ is cmov so slow? Does it kill register renaming or
| something like that?
| dgrunwald wrote:
| cmov itself isn't slow, it has a latency of 2 cycles on
| Intel; and only 1 cycle on AMD (same speed as an add).
| However, cmov has to wait until all three inputs
| (condition flag, old value of target register, value of
| source register) are available, even though one of those
| inputs ends up going unused.
|
| A correctly predicted branch allows the subsequent
| computation (using of the result of the ?: operator) to
| start speculatively after waiting only for the relevant
| input value, without having to wait for the condition or
| the value on the unused branch. This could sometimes save
| hundreds of cycles if an unused input is slow due to a
| cache miss.
| dataflow wrote:
| Ahh, thank you! Makes sense.
| bigiain wrote:
| I wonder if there's anyone on earth who needs nicely
| formatted human readable file sizes that's worried about
| the difference between one or two cpu cycle branching
| instructions?
|
| There might be a few guys at FAANG who have a planet-
| scale use case for human readable file sizes. But surely
| "performance optimising" this is _purely_ code golf
| geekiness?
|
| (Which is a perfectly valid reason to do it, but I'm
| gonna choose the most obvious to the next progerammer
| reading it version over one that 50% or 500% or 5000%
| fast in almost any use case I can think I'm like to need
| this... I mean, it's only looking for 6 prefixes "KMGTPE"
| a six line case statement would work for most people?)
| bigiain wrote:
| Actually, I just realised. This is (probably a small part
| of) why "calculate all sizes" in Mac finder windows is so
| slow. I already mentioned Apple in FAANG, but I guess
| someone at Microsoft and people who work on Linux file
| brokers care too. And whoever maintains the -h flag
| codepaths in all the Unix-like utils that support it?
| dataflow wrote:
| Confused what this has to do with calculating file sizes.
| Time spent computing file sizes is dwarfed by I/O, right?
| initplus wrote:
| CMOV is slow because x86 processors will not speculate
| past a CMOV instruction. They do speculate past
| conditional jumps, so those are more performant.
|
| This same property makes CMOV useful in Spectre
| mitigation, see
| https://llvm.org/docs/SpeculativeLoadHardening.html
|
| Keeping CMOV slow is now an important security feature.
| dataflow wrote:
| They don't speculate past a CMOV _at all_? Like even if
| the next instruction has nothing to do with the CMOV 's
| output?
| saghm wrote:
| I think out of order processing is considered different
| than speculative execution, but I could be remembering my
| architecture class wrong
| colejohnson66 wrote:
| Out-of-order just means it can rearrange the decoded uops
| in a way to keep the execution units at full capacity.
| So, if an instruction needs the ALU, but it's busy, and
| the next one needs the AGU (address generation unit) and
| doesn't depend on the results of the ALU one, it can
| "dispatch" the AGU one while the ALU one waits for the
| pipeline to move.
|
| Speculative execution refers more towards the decoder/uop
| generation side of the processor (the "in-order" side). A
| normal "in-order" processor, upon encountering a
| conditional jump, would wait until the pipeline is
| finished to check if it should jump or not. It does it by
| inserting "bubbles" into the pipeline - essentially doing
| nothing but waiting.
|
| Speculative execution (or branch prediction) would say,
| "I think the branch _will_ be taken based on X, Y, Z,"
| and then keep the pipeline full in the process. If the
| prediction was right, congratulations! You just saved
| dozens of clock cycles that otherwise would've been
| wasted. If it was wrong, no worries. The pipeline is then
| flushed; all the speculated instructions' results are
| tossed (before they're "written back"). Then the
| processor resumes operation on the correct branch.
|
| Speculative execution doesn't necessitate an out-of-order
| architecture, and visa-versa. Just a pipelined one. It's
| perfectly possible to have an out-of-order architecture
| that doesn't speculate, or a speculative one that is
| completely "in-order", but they work hand-in-hand, and it
| makes sense to have both if you have one.
| dataflow wrote:
| Is it safe to say speculation is about what to do with
| instructions following conditionals, and OoO is about
| what to do with instructions following non-conditionals?
| colejohnson66 wrote:
| Roughly, yes
| rot13xor wrote:
| This email thread from Linus might be interesting:
| https://yarchive.net/comp/linux/cmov.html
| colejohnson66 wrote:
| My understanding of out-of-order (and pipelined) CPUs is
| limited, but it's interesting that CMOV isn't interpreted
| as a "Jcc over MOV" by the decoder. That would allow
| using the branch predictor. Would it be too complex or
| does the microarchitecture not even allow it?
| dataflow wrote:
| I think that thread is where I first learned this
| actually. Didn't remember it until you linked it now,
| thanks for posting it!
| ncann wrote:
| If the if/else is simple the compiler should be able to
| optimize that anyway.
| hvdijk wrote:
| Both ?: and if-else have cases where they can be compiled
| into cmov type instructions and where they cannot. Given
| int max(int a, int b) { if (a > b) return a; else return b;
| }, a decent compiler for X86 will avoid conditional
| branches even though ?: wasn't used. Given int f(int x) {
| return x ? g() : h(); }, avoiding conditional branches is
| more costly than just using them, even though ?: was used.
| nn3 wrote:
| Besides log()'s implementation is certainly not branch-less.
|
| It's the ostrich approach: if you don't see the branches they
| don't matter.
| kruczek wrote:
| Exactly. As the article itself mentions:
|
| > Granted it's not very readable and log / pow probably makes
| it less efficient
|
| So, the "improved" solution is both less readable and probably
| less efficient... where is the improvement then?
| xfer wrote:
| The real question is why is it a bug to report 1 mB instead of
| 999.9 kB for human readable output? It seems like a nice
| excursion to FP related pitfalls, but i don't think this is a
| problem to get entangled in that.
| Groxx wrote:
| Because it doesn't print 999.9 kB _or_ 1 mB.
|
| It prints 1000.0 kB.
| xfer wrote:
| I still wouldn't consider it a bug since we are throwing
| lots of lsbs anyways. It matters even less when we are
| talking about Peta/Exa bytes.
| cellularmitosis wrote:
| I guarantee a design team would take one look at 1000.0kB
| and kick it back as a bug
| ceronman wrote:
| Simplicity FTW. The simple loop version is very easy to
| understand. It's probably really fast, as it's just a loop over
| seven items. And more importantly it's more correct. It doesn't
| use floating point arithmetic, so you don't have to worry about
| precision issues.
|
| The logarithmic approach is harder to reason about, prone to
| bugs (as proven by this post). I'm baffled at the fact that
| tons of people considered it a more elegant solution! It's
| completely the opposite!
| sixothree wrote:
| If it were me in my programming language, I would just use
| Humanizr and be freaking done with it.
| rkagerer wrote:
| Not sure why some programmers these days have aversion to
| simple loops and other boring - but readable - code.
|
| Instead we have overused lambdas and other tricks that started
| out clever but become a nightmare when wielded without
| prudence. In this article, the author even points out why not
| to use his code:
|
| _Note that this started out as a challenge to avoid loops and
| excessive branching. After ironing out all corner cases the
| code is even less readable than the original version.
| Personally I would not copy this snippet into production code._
| hnedeotes wrote:
| I'm not against using for loops when what you need is an
| actual loop. The thing is most of the times, previously, _for
| loops_ where actually doing something for which there are
| concepts that express exactly what was being done - though
| not in all languages.
|
| For instance, _map_ - I know that it will return a new
| collection of exactly the same number of items the iterable
| being iterated has. When used correctly it shouldn 't produce
| any side-effects outside the mapping of each element.
|
| In some languages now you have _for x in y_ which in my
| opinion is quite ok as well, but still to change the
| collection it has to mutate it, and it 's not immediate what
| it will do.
|
| If I see a _reduce_ I know it will iterate again a definite
| number of times, and that it will return something else than
| the original iterable (usually), _reducing_ a given
| collection into something else.
|
| On the other hand _forEach_ should tell me that we 're only
| interested in side-effects.
|
| When these things are used with their semantic context in
| mind, it becomes slightly easier to grasp immediately what is
| the scope of what they're doing.
|
| On the other hand, with a _for_ (especially the common, old
| school one) loop you really never know.
|
| I also don't understand what is complex about the functional
| counterparts - _for (initialise_var, condition, post /pre
| action)_ can only be simpler in my mind due to familiarity as
| it can have a lot of small nuances that impact how the
| iteration goes - although to be honest, most of the times it
| isn't complex either - but does seem slightly more complex
| and with less contextual information about the intent behind
| the code.
| jasonkester wrote:
| _When used correctly it shouldn 't produce any side-effects
| outside the mapping of each element._
|
| But that's just a social convention. There's nothing
| stopping you from doing other things during your map or
| reduce.
|
| In practice, the only difference between Map, Reduce and a
| For loop is that the first two return things. So depending
| on whether you want to end up with an array containing one
| item for each pass through the loop, "something else", or
| nothing, you'll use Map, Reduce or forEach.
|
| You can still increment your global counters, launch the
| missiles or cause any side effects you like. "using it
| correctly" and not doing that is just a convention that you
| happen to prefer.
| hnedeotes wrote:
| That is true (less so in FP languages though), but the
| for loop doesn't either - indeed I do prefer it _most_ of
| the times, I think its a reasonable expectation to
| provide the most intention revealing constructs when
| possible, it 's also easier to spot "code smells" when
| using those. The exceptions I make is when there's
| significant speed concerns/gains, when what you're doing
| is an actual loop, when the readability by using a loop
| is improved.
|
| (and I haven't read the article so not even sure I agree
| with the example there, this was more in general terms)
| zimpenfish wrote:
| > For instance, map - I know that it will return a new
| collection of exactly the same number of items the iterable
| being iterated has.
|
| Unless you're using Perl - "Each element of LIST may
| produce zero, one, or more elements in the generated list".
| hibbelig wrote:
| Perl implements flatMap and calls it map :-)
| codedokode wrote:
| For me, code with _reduce_ is less readable than a loop.
| With loop everything is obvious, but with reduce you need
| to know what arguments in a callback mean (I don 't
| remember), and then think how the data are transformed.
| It's an awful choice in my opinion. Good old loop is so
| much better.
| cerved wrote:
| Guido?
| foxes wrote:
| I disagree entirely. In most imperative programming
| languages, you can shove any sort of logic inside a loop,
| more loops, more branches, creating new objects, its all
| fair game.
|
| Fold and map in functional languages are often much more
| restrictive in a sense. For example, with lists, you
| reduce down a collection [a]->a to a single object, or
| produce another collection with a map [a]->[a]. So map
| and fold etc are much more restrictive. That's what makes
| it clearer.
| [deleted]
| hnedeotes wrote:
| It can definitively happen, but I think more times than
| not the others are more readable.
|
| To be honest this seems to be a familiarity thing > but
| with reduce you need to know what arguments in a callback
| mean
|
| If I didn't know _for_ it would be mind boggling what
| those 3 things, separated by semicolons, are doing It
| doesn 't look like anything in the usual language(s)
| they're implemented. It's the same with _switch_.
|
| The only thing both of them have, _for_ and _switch_ ,
| and helps, is that languages that offer it and aren't FP
| usually use the same *C* form across all, whereas
| reduce's args and the callback args vary a bit more
| between languages, and specially between mutable and
| immutable langs.
|
| I still prefer most of the time the functional specific
| counterparts.
| verinus wrote:
| if you are used to imperative programming, then yes.
|
| But in a for loop anything can happen- from a map to a
| reduce to a mix, to whatever convoluted logic the dev
| comes up with.
| watwut wrote:
| And it is usually very easy and straightforward to see
| what is going on inside.
| ajuc wrote:
| Technically you can implement map as reduce ;)
|
| But yes - for me (defn factorial [n]
| (reduce * (range 1 (inc n))))
|
| is slightly more readable than def
| factorial(n): result = 1 for i in
| range(2,n+1): result *= i
| return result
|
| I mean in this case the name kinda makes it obvious
| anyway :)
|
| If the operation is conceptually accumulating something
| over the whole collection and if it's idiomatic in the
| language I'm using - I will use reduce. Same with map-y
| and filter-y operations.
|
| But if I have to do some mental gymnastics to make the
| operation fit reduce - for loop it is. Or generator
| expression in case of python.
| distances wrote:
| Indeed. I rarely encounter basic loops in code reviews
| now, so seeing one is definitely a small alert to do an
| extra thorough review of that part.
| kamray23 wrote:
| Yeah, I'd much rather have something like
| congruence_classes m l = map (\x -> ((x ==) . (`mod` m)) l)
| [0..m-1]
|
| than def congruence_classes(m, l):
| sets = [] for i in range(m): sets
| += [[]] for v in l: sets[v % m] +=
| [v] return sets
|
| For-in is very neat and nice but it still takes two loops
| and mutation to get there. Simple things are sometimes
| better as one-line maps. Provability is higher on
| functional maps too.
|
| Same one-liner in (slightly uglier) Python:
| def congruent_sets(m, l): return list(map(lambda x:
| list(filter(lambda v: v % m == x, l)), range(m)))
| gjulianm wrote:
| The one liner is far less readable and under the hood it
| actually is worse: for each value in [0, m] you're
| iterating l and filtering it, so it's a O(n^2) code now
| instead of O(n). That mistake would be far easier to
| notice if you had written the exact same algorithm with
| loops: one would see a loop inside a loop and O(n^2)
| alarms should be ringing already.
|
| Ironically, it's a great example of why readability is so
| much more important than conciseness and one liners.
| verinus wrote:
| I agree and despite beeing a fan (kind of a convert from
| OO) of FP I am often wondering about readability of FP
| code.
|
| One idea I have is, that often FP code is not modularized
| and violates the SOLID principle in doing several things
| in one line.
|
| there are seldom named subfunctions where the name
| describe the purpose of the functions- take lamdas as an
| example: I have to parse the lamda code to learn what it
| does. Even simple filtering might be improved (kinda C#):
|
| var e = l.Filter(e => e.StartsWith("Comment"));
|
| vs.
|
| var e = l.Filter(ElementIsAComment);
|
| or even using an extension method:
|
| var e = l.FindComments();
|
| sorry I could not come up with a better example- I hope
| you get my point...
| kamray23 wrote:
| True, it is computationally worse, though it's O(nm) so
| applying m at compile time to form a practical use as I
| used it will turn it into to O(n) in practice.
|
| But that much is immediately obvious since it's mapping a
| filter, that is, has a loop within a loop.
|
| I did consider the second one to also take quadratic time
| though. I forgot that in python getting list elements by
| index is O(1) instead of O(n) which is what I'm
| personally used to with lists.
|
| It's also true that you can replace the filter with
| [ v | v <- l, v `mod` m == x ]
|
| but that's not as much fun as
|
| (x ==) . (`mod` m)
|
| I just love how it looks and it doesn't personally seem
| any less clear to me, maybe a bit more verbose.
| ummonk wrote:
| "I forgot that in python getting list elements by index
| is O(1) instead of O(n) which is what I'm personally used
| to with lists."
|
| Have you considered that maybe this is a sign you're too
| deep into using impractical programming languages?
|
| Cleanness for immutable data structures aside, linked
| list are a very poor way to store data given the way
| computer architectures are designed.
| dragonwriter wrote:
| > Have you considered that maybe this is a sign you're
| too deep into using impractical programming languages?
|
| "Languages that use 'list' for linked lists and have
| different names for other integer-indexable ordered
| collections" aren't necessarily "impractical".
| ummonk wrote:
| Why not just use a list comprehension?
| def congruent_sets(m, l): return [[v for v in l
| if v % m == i] for i in range(m)]
| 988747 wrote:
| Isn't that unnecessary quadratic algorithm (nested loops,
| m*l iterations, instead of m + l)?
| ummonk wrote:
| Yes, but that's the case with all the functional
| approaches proposed.
|
| If Python were focused on functional programming it would
| have a utility function for this similar to
| itertools.groupby (but with indices in an array instead
| of keys in a dictionary).
| nvarsj wrote:
| Yes, this plagues JDK8+ code. Every fashionable Java coder
| has to use an overly complex, lazy stream vs a simple loop in
| every case.
| BrandoElFollito wrote:
| Disclamer: amateur developer for 25 years, no formal
| education in that area
|
| a loop that iterates over indices when I want elements is not
| readable, e.g. I prefer for element in
| elements:
|
| rather than for (i = 0 , i < len(elements),
| i++) { element = elements[i] ...
|
| This is maybe where this aversion comes from, people usually
| [citation needed] want to iterate over elements, rather than
| indices.
| hawski wrote:
| I find that many times in more complex loops you need the
| index as well. Sometimes for as mundane reason as logging.
| BrandoElFollito wrote:
| Yes, my code is not that complicated and I use languages
| that are rather high level (Python, Golang, JS with Vue)
| so I needed the index I think once when I had to remove
| an element from an array in JS and for some reason I was
| not using lodash.
|
| But yes, there are of course cases where the index could
| be needed, I was merely commenting on the aversion part
| for generic developers.
| xelxebar wrote:
| I can't comment on the social phenomenon here, but there is
| indeed a decent technical argument for avoiding for loops
| when possible.
|
| In a nutshell, it's kind of like "prinicple of least
| priviledge" applied to loops. Maps are weaker than Folds
| which are weaker than For loops, meaning that the stronger
| ones can implement the weaker ones but not vice-versa. So it
| makes sense to choose the weakest version.
|
| More specifically, maps can be trivially parallelized; same
| for folds, but to a lesser degree, if the reducing operation
| is associative; and for-loops are hard.
|
| In a way, the APL/J/K family takes this idea and explores it
| in fine detail. IMHO, for loops are "boring and readable" but
| only in isolation; when you look at the system as a whole
| lots of for loops make reasoning about the global behaviour
| of your code a lot harder for the simple reasone that for-
| loops are too "strong", giving them unweildy algebraic
| properties.
| qayxc wrote:
| While these are all valid and well thought out arguments,
| in this particular example, a whole class of problems and
| bugs were introduced specifically by avoiding simple loops.
|
| Not to mention the performance implications.
| Parallelisation, composability and system thinking are
| sometimes overkill and lead to overengineering.
| caf wrote:
| The article says the looping versions also had the bug.
| qayxc wrote:
| Correction: a bug. This is important to note, because
| only the non-loop version had precision issues.
| gjulianm wrote:
| > So it makes sense to choose the weakest version.
|
| Only if it's actually more readable. The principle of least
| privilege does not give you any benefit when talking about
| loop implementations.
|
| > More specifically, maps can be trivially parallelized;
|
| This argument is repeated time and time again but I've
| never actually seen it work. Maps that can be trivially
| parallelized aren't worthy to parallelize most of the time.
| In the rare case it's both trivial and worthy, it's because
| the map function (and therefore the loop body) are side-
| effect free, and for those rare cases you don't care too
| much about the slightly extra effort of extracting the loop
| body into a function.
|
| > when you look at the system as a whole lots of for loops
| make reasoning about the global behaviour of your code a
| lot harder for the simple reason that for-loops are too
| "strong"
|
| Code is too strong in general. Reasoning about the global
| behavior of code is difficult if the code itself is
| complex. Nested maps and reduces will be equally difficult
| to comprehend. The fact that a map() function tells you
| that you're converting elements of lists does not save you
| from understanding what is that conversion doing and why.
|
| Sometimes loops will be better for readability, sometimes
| it will be map/reduce. Saying that for loops always make it
| harder to reason about the code does not make too much
| sense in my opinion.
| hnedeotes wrote:
| I agree with the no silver bullet thing - and written on
| another reply I don't even know if I agree with the
| example in the article.
|
| > The fact that a map() function tells you that you're
| converting elements of lists does not save you from
| understanding what is that conversion doing and why.
|
| It can actually, say you have a query that comes in, this
| calls a function that fetches records from the database,
| it's not a basic query, it has joins, perhaps a subquery,
| etc. Then you have another function that transforms the
| results into whatever presentational format, decorates,
| wtv, those results, and it's also more than a few basic
| couple lines of logic.
|
| And now you have a bug report come in, that not all
| expected results are being shown.
|
| If you have func does_query -> loop
| transforms
|
| You have 3 possibilities, the problem is on the storage
| layer, the problem is on the query, the problem is on the
| loop. You read the query, because the bug is subtle, it
| seems ok, so now you move to the loop. It's a bit complex
| but seems to be correct too. Now you start debugging
| what's happening.
|
| If you have func does_query -> func
| maps_results
|
| You know it's either underlying storage or the query.
| Since the probability of the storage being broken is less
| plausible, you know it must be the query. In the end it's
| a synch problem with something else, and everything is
| right, but now you only spent time on reproducing the
| query and being sure that it works as expected.
| codedokode wrote:
| Loops are easier to read. With functions like _reduce_ you
| have to solve a puzzle every time to understand what the
| code is doing (this is also true for functional style of
| programming in general).
|
| > More specifically, maps can be trivially parallelized;
| same for folds, but to a lesser degree, if the reducing
| operation is associative; and for-loops are hard.
|
| In a typical Javascript code _reduce_ operation will not be
| parallelized. It actually can be slower than a loop because
| of overhead for creating and calling a function on every
| iteration.
|
| > when you look at the system as a whole lots of for loops
|
| A code with lot of loops is still more readable than a code
| with lots of nested _reduce_ s.
| bryanrasmussen wrote:
| >Loops are easier to read. With functions like reduce you
| have to solve a puzzle every time to understand what the
| code is doing
|
| I think that is a function of familiarity, if you use
| reduce a lot it will be as easy to read as a loop -
| perhaps easier because more compact - there is a downside
| to reading more lines for some people, at some point
| verbosity becomes its own source of illegibility
| (although any loop that can easily be turned into a
| reduce probably won't be excessively verbose anyway)
|
| Of course all that is just on the personal level, you ,
| by using and reading more code with reduce in it will
| stop finding reduce less easy to understand than loops -
| but the next programmer without lots of reduce experience
| will be in your same boat.
| cerved wrote:
| loops are harder to read. What does it do, map, reduce,
| send emails to grandma?
|
| In JavaScript, the reduce callback is created once and
| called repeatedly. For loops are pretty much always the
| fastest possible way because they use mutable state. They
| are also a really good way of creating unreadable
| spaghetti that does things you don't want them to.
|
| I'm not sure what you mean by nested reduces. Chained
| reduce functions are easy to follow
| watwut wrote:
| You can send email to grandma from both map and reduce.
| girvo wrote:
| I disagree quite strongly, in that this is simply a
| function of familiarity. Reduce is no more or less
| readable than for (especially the C style for -- imagine
| trying to work out what the three not-really-arguments
| represent!)
| chousuke wrote:
| Very often processes are naturally modelled as a series of
| transformations. In those cases, writing manual loops is
| tedious, error-prone, harder to understand, less composable
| and potentially less efficient (depending on language and
| available tools) than using some combination of map, filter
| and reduce.
| dragonwriter wrote:
| > Not sure why some programmers these days have aversion to
| simple loops and other boring - but readable - code.
|
| Like goto, basic loops are powerful, simple constructs that
| tell you nothing at all about what the code is doing.
| For...in loops in many languages are a little better, but
| map, reduce, or comprehensions are much more expressive as to
| what the code is doing, but mostly address common cases of
| for loops.
|
| While loops are weakly expressive (about equal to for...in),
| but except where they are used as a way (in language without
| C-style for loops) but there is less often a convenient
| replacement.
| kmote00 wrote:
| Update title: this is from 2019
| mjevans wrote:
| The author's lookup table is incorrect.
|
| The question being answered clearly wanted base2 engineering
| prefix units, rather than the standard base10 engineering prefix
| units.
|
| suffixes = [ "EB", "PB", "TB", "GB", "MB", "KB", "B" ]
|
| magnitudes = [ 2^60, 2^50, 2^40, 2^30, 2^20, 2^10, 2^0 ] //
| Pseudocode, also 64 bit integers required. (Compilers might
| assume unsigned 32 for int)
| returningfory2 wrote:
| That code snippet is explicitly introduced in the article as
| _not_ the author 's.
| asdf3243245q wrote:
| That is not the author's code. That is pseudocode for one of
| the example answers that he is improving on.
|
| The author's code gives an option for the units:
|
| int unit = si ? 1000 : 1024;
| Fornax96 wrote:
| If you do this you should add an 'i' to the prefixes to denote
| that you mean the binary notation. e.g: kiB, MiB, GiB, TiB, etc
| comicjk wrote:
| When I'm explaining logarithms, I find it helps to relate it to
| the number of digits. This code is a good example of the concept:
| you don't need log, just convert the int to a string and check
| its length. A string with 1-3 digits is bytes, 4-6 is kb, etc.
___________________________________________________________________
(page generated 2021-06-17 23:03 UTC)