[HN Gopher] Incorrect expression calculation between programming...
___________________________________________________________________
Incorrect expression calculation between programming languages
This expression shows that we have several disagreements between
programming languages about what is the end result: ===== EXPR =
(((((((788)*(8.46))))+8342*1.803-1))*4186.4*(15))*(((22%284/((7530/
((2)*(((((25))-421))))))*597%2663)+7283.8-9.60+167.8644%((3))))+(88
71) POSTGRESQL = 8291561284461.33301440 SQUILU = 8291561284461.3
JAVA = 8.291561284461331E12 D = 8.29156e+12 SQLITE =
8290383058308.3 PHP = 8035491468054 JAVSCRIPT = 8036090802426.098
MYSQL = 8036090802312.071 PYTHON = 1.1107636287e+13 RUBY =
11107636286950.146 LUA = 11665910614443 =====
Author : mingodad
Score : 59 points
Date : 2021-08-06 11:24 UTC (1 days ago)
| mingodad wrote:
| And making all operands to modulo operator "%" integer:
|
| =====
|
| EXPR = (((((((788)*(8.46))))+8342*1.803-1))*4186.4*(15))*(((22%28
| 4/((7530/((2)*(((((25))-421))))))*597%2663)+7283.8-9.60+167%((3))
| ))+(8871)
|
| D = 8.29038e+12
|
| JAVA = 8.290383058308305E12
|
| MYSQL = 8034912576159.046
|
| POSTGRESQL = 8290383058308.307200
|
| SQLITE = 8290383058308.3
|
| SQUILU = 8291561284461.3
|
| JAVASCRIPT = 8034912576273.071
|
| PHP = 8035491468054
|
| AMPL = 8.03491e+12
|
| GAMS = 8.03491E+12
|
| PYTHON = 1.11064580608e+13
|
| RUBY = 11106458060797.121
|
| LUA = 11664732388290
|
| ====
| mingodad wrote:
| After removing all modulo operations and transforming all numbers
| to floating point:
|
| ====
|
| EXPR = (((((((788.0) _(8.46))))+8342.0_ 1.803-1.0)) _4186.4_
| (15.0)) _(((22.0 /((7530.0/((2.0)_(((((25.0))-421))))))*597.0)+72
| 83.8-9.60+167.0))+(8871.0)
|
| SQUILU = 8259816920615.1
|
| LUA = 8259816920615.1
|
| JAVASCRIPT = 8259816920615.111
|
| SQLITE = 8259816920615.11
|
| POSTGRESQL = 8259816920615.11377654520912550160000
|
| MYSQL = 8259816920615.113
|
| AMPL = 8.25982e+12
|
| PHP = 8259816920615.1
|
| RUBY = 8259816920615.111
|
| PYTHON = 8.25981692062e+12
|
| ====
| ayjtyjtyj wrote:
| See this interesting paper on the possible choices of
| definition for div and mod:
|
| RT Boute, "The Euclidean definition of the functions div and
| mod" (1992)
|
| https://biblio.ugent.be/publication/314490/file/452146.pdf
| [deleted]
| miga wrote:
| Your expressions omits many necessary operators, and thus
| becomes ambiguous.
| comex wrote:
| It's because Hacker News parsed the asterisks in the
| expression as italic markers.
| psyklic wrote:
| This is solely due to differences in the / and % operators:
| # int/int -> int POSTGRESQL = 8291561284461.33301440
| SQUILU = 8291561284461.3 JAVA = 8.291561284461331E12
| D = 8.29156e+12 # int/int -> float LUA =
| 11665910614443 PYTHON3 = 11665910614443.387 #
| int/int -> float, UNIQUE: pos%neg -> neg JAVSCRIPT =
| 8036090802426.098 MYSQL = 8036090802312.071 # single-
| precision FLOAT # int/int -> int, UNIQUE:
| negint/posint -> negint (the floor) PYTHON2 =
| 1.1107636287e+13 RUBY = 11107636286950.146 #
| int/int -> int, UNIQUE: negfloat%posint -> negint (the ceil)
| SQLITE = 8290383058308.3 # int/int -> float, UNIQUE:
| negfloat%posint -> negint (the ceil) PHP = 8035491468054
| begueradj wrote:
| interesting note
| specialist wrote:
| Interesting.
|
| What's the correct answer?
|
| Which programming languages specify which parts of IEEE 754
| they follow (or not)?
|
| https://en.wikipedia.org/wiki/IEEE_754
|
| Ditto rendering of floating point numbers. Here's a prior
| thread about Steele & White, Grisu, Ryu:
|
| "Here be dragons: advances in problems you didn't even know you
| had" https://news.ycombinator.com/item?id=24917659
| kazinator wrote:
| They are possibly all correct.
|
| Correct means that the requirements of a documented
| specification are being followed.
| rmah wrote:
| There is no correct answer. There is no correct answer. The
| various ways different languages handle implicit type
| conversion with division and modulo operations are all both
| correct and incorrect at the same time. It's really an
| arbitrary choice. In fact, there are more choices than
| presented above. I think, for example, Perl6, uses rational
| numbers in some of the above situations.
| chowells wrote:
| The correct answer is not making the computer guess what you
| mean. That's the root problem here. You're being super-sloppy
| about specifying what actual operations you want to take
| place. What are the types of the operands? What are the
| semantics of the arithmetic operators for the pairs of
| operand types you get?
|
| Without bothering to tell the computer what you want for the
| types or select the correct operators for the types you
| provided, you're falling back on guessing. Not every language
| guesses the same way, because not every language designer has
| the same guess what people meant.
|
| My ideal is a language that tells you that expression is bad
| and to actually clarify what you mean. But a lot of people
| seem to hate having to explicitly communicate their intent.
| [deleted]
| guenthert wrote:
| Well, ideally you'd want to treat int/int -> rational. The
| original form is quite obfuscated, some of the parentheses
| are to enforce evaluation of the given string as number (and
| the various programming languages will differ as what number
| that'll be, due to representation of decimal fractions and
| type conversion), some parenthesis are plainly superfluous,
| yet still there is remaining ambiguity (how is a%b/c to be
| interpreted? Most programming languages will do this
| left->right, but better make that explicit). Prefix notation
| to the rescue:
|
| Common Lisp (with *read-default-float-format* -> SINGLE-
| FLOAT)
|
| CL-USER> (+ (* (+ (* 788 8.46) (1- (* 8342 1.803))) 4186.4 15
| (+ (* (/ (mod 22 284) (/ 7530 (* 2 (- 25 421) (mod 597
| 2663))))) 7283.8 -9.60 (mod 167.8644 3))) 8871)
|
| 8.03609e12
|
| Wolfram Alpha finds for
| (((((((788)*(8.46))))+8342*1.803-1))*4186.4*(15))*(((mod [22,
| 284]/((7530/((2)*(((((25))-421))))))*mod[597,
| 2663])+7283.8-9.60+mod[167.8644, ((3))]))+(8871)
|
| 8.03609080242609957376254980079681274900398406374501992031872
| *10^12
| mjn wrote:
| IEEE 754 doesn't really have anything to say about which
| semantics you should choose for int/int division. _If_ you
| choose the semantics of casting both operands to floating
| point and then dividing, IEEE 754 specifies both 1) how the
| int- >float conversion should happen, and 2) how the
| float/float division should happen. But if you choose the
| semantics that int/int division returns an int without any
| floating-point conversions (like C's '/' operator), then no
| floating point numbers enter into the question at all, and
| it's out of scope for IEEE 754.
| _moof wrote:
| Over thirty years of programming I've slowly become
| convinced that implicit conversions are the devil.
| andi999 wrote:
| This devil allows high productivity though.
| andybak wrote:
| Must be down to all those idle hands he can bring to bear
| on a given task.
| tialaramex wrote:
| Not everybody is convinced that it's "more productive" to
| produce more bugs.
| jl6 wrote:
| Bingo. When performance is the overriding goal, it is
| often a matter of choosing which deals to do with which
| devils.
| Pinus wrote:
| So, we have (at least) different evaluation orders, different
| meanings of the % operator (How are negative numbers handled?),
| different meanings of the / operator (is 10/3=3 or 3.3333 --
| notice that Python3 joins the 8.29e+12 fold!). This shows two
| things: 1) Even though it is syntactically correct in N different
| languages, it does not necessarily mean the same thing, and 2)
| floating-point math has many traps. Neither should be news to the
| HN readership.
| hansvm wrote:
| This kind of thing can bite you even when operating purely on
| integers. E.g., for a long time (it's been fixed for over a dozen
| years by now though), Python implemented x%n with an intermediate
| cast to float, with predictably bad results on inputs larger than
| typical test cases. I had the damnedest time tracking down the
| culprit since I assumed it had to be serialization, hashing, or
| one of the standard culprits --- not that integer math was
| broken.
| [deleted]
| mingodad wrote:
| And after removing all modulo operations:
|
| ====
|
| EXPR = (((((((788)*(8.46))))+8342*1.803-1))*4186.4*(15))*(((22/((
| 7530/((2)*(((((25))-421))))))*597)+7283.8-9.60+167))+(8871)
|
| SQUILU = 8515287402650.3
|
| SQLITE = 8515287402650.34
|
| POSTGRESQL = 8515287402650.347200
|
| D = 8.51529e+12
|
| JAVA = 8.515287402650345E12
|
| MYSQL = 8259816920501.086
|
| JAVASCRIPT = 8259816920615.111
|
| PHP = 8259816920615.1
|
| LUA = 8259816920615.1
|
| AMPL = 8.25982e+12
|
| GAMS = 8.25982E+12
|
| RUBY = 7701542593121.873
|
| PYTHON = 7.70154259312e+12
|
| ====
| oshiar53-0 wrote:
| PYTHON3 = 8259816920615.111
| fishmaster wrote:
| Julia 1.3.1: 8.259816920615111e12
| tromp wrote:
| bc -l = 8259816920615.11375936705619635555
| [deleted]
| svnpenn wrote:
| You couldnt come up with a simpler example? Youve got at least 12
| operations there. Pretty much a single division operation wouldve
| worked about the same
| banana_giraffe wrote:
| Different languages have different rules around some math
| operators, notably around order of operations and how % and /
| handle floating point values. There are much simpler expressions
| that will yield differences.
|
| Also, you appear to be using Python 2, the results are different
| with any modern version of Python.
| banana_giraffe wrote:
| And here are the two differences I think your expression is
| hitting on: Expression: 750/300
| Python 2.7: 2 Python 3.9: 2.5 C: 2.000000
| SQLite: 2 Node: 2.5 Java: 2 Go: 2
| Expression: -123%10 Python 2.7: 7 Python 3.9: 7
| C: -3.000000 SQLite: -3 Node: -3 Java:
| -3 Go: -3
|
| There might be more. Though, there's a ton of needless
| obfuscation in your expression.
| unwind wrote:
| Certainly not floating point results in C for either of
| those.
|
| All literals shown (750, 300, -123 and 10) are of type 'int',
| so the results would be, too.
| banana_giraffe wrote:
| Yep, I coerced the result to floating point in my harness.
|
| If anyone cares to look: https://pastebin.com/7tLrs28V
|
| I'm probably done, it's a mildly interesting side quest,
| but really, this is just reinforcing that different
| languages do things differently.
| MauranKilom wrote:
| Other than nerdsniping, what is the point of this expression?
|
| If you wanted to show how different languages treat modulo, type
| conversions, division, etc., you could just show individual
| examples. That would be significantly clearer.
|
| Was there some practical reason behind creating this expression,
| or is it just obfuscation?
| hinkley wrote:
| A big part of the oft-overlooked notion of Information
| Architecture are the twin concepts of Source of Truth and System
| of Record. Many systems mix or conflate the two or don't consider
| them at all, other than subconsciously when wrestling with issues
| of code duplication (split SoT).
|
| If the result of a calculation is that important to the
| functioning of your code, then having three implementations in
| multiple languages is just madness. You need to pick one to
| believe, or constantly deal with random catastrophes. Personally
| I enjoy very much not being woken up at 7 am EST to solve
| production issues. Almost as much as I hate other people getting
| kudos for problems that we should have not signed up for in the
| first place. Arsonist-firefighters exist in every dark corner of
| the programming world, and in much greater numbers than actual
| arsonist-firefighters.
|
| From a technology selection standpoint, all of this info is
| extremely important, because it will inform both my choice of
| tools and my immediate task list to deal with any answers I don't
| like. But if you're wrestling with this every day, you've already
| fucked up.
| NotSwift wrote:
| These are some shocking differences. How did you come up with
| this expression?
| mingodad wrote:
| After looking for a text generator for grammars I found this
| https://github.com/dmbaturin/bnfgen and then to try understand
| the underlying algorithm I came out with a C simple program for
| a simple expr grammar see it here
| https://github.com/dmbaturin/bnfgen/issues/2#issuecomment-89...
| and also a thread on sqlite forum here
| https://sqlite.org/forum/forumpost/6885cf9e21
| fishmaster wrote:
| Julia 1.3.1: 8.036090802426098e12
| gus_massa wrote:
| Try to edit your post and add a \ before each * so it is not
| interpreted as italics here.
|
| Have you tried to simplify it? My guess is that the problem is
| not in the last "+(8871)".
| [deleted]
| miga wrote:
| Haskell: =====
|
| (%) = Data.Fixed.mod'
|
| expr :: Double = 8.036090802426098e12
|
| expr :: Rational = 630330872315297185317 % 78437500
|
| fromRational (expr :: Rational) :: Double = 8.0360908024261e12
| amichal wrote:
| Fairly early on in my career I was on a team writing a GUI
| programming environment (think old school flow charts) that
| generated ASP (classic) or Java backends. We allowed simple
| expressions in assignments with the basic arithmetic operators
| and functions. We parsed them into a tiny AST and output Java or
| ASP code for them with lots of explicit parens and casts. After
| fiddling with minor differences in precedence, associativity and
| implicit casts we still had some cases that did not match.
| Pairing with a more senior dev we wrote a C program to generate
| and compare a large number (tens of millions) of random
| expressions trying to explore the important variables (small and
| large floats. Floats that cause funny rounding. Long sequences of
| almost the same precedence etc).
|
| We got all three languages to agree to full precision for almost
| every case but in each run there were stubbornly alway a few
| dozen we couldn't get to match for non obvious and seeming random
| reasons.
|
| This was a prototype that never saw real production use and we
| spent a couple of weeks on it... it always bothered me that we
| never understood that last 0.00001%
| SavantIdiot wrote:
| You can't hold a language responsible for "mistakes" if you don't
| understand how the language works. Quotes intentional.
| anthropodie wrote:
| For Go, we get compilation error
|
| ./prog.go:8:129: invalid operation: 167.864 % 3 (operator % not
| defined on untyped float)
| ben-schaaf wrote:
| It's hardly incorrect that different languages have different
| semantics, especially considering the mix of types and use of %
| in that expression. You could just as well complain that they
| don't all print floating point numbers in the exact same way.
| brudgers wrote:
| And that is why people still use FORTRAN.
| mingodad wrote:
| Using https://www.onlinegdb.com/online_fortran_compiler
|
| FORTRAN = 8.51528699E+12
|
| ====
|
| Program Hello
|
| Print *, (((((((788)*(8.46))))+8342*1.803-1))*4186.4*(15))*(((2
| 2/((7530/((2)*(((((25))-421))))))*597)+7283.8-9.60+167))+(8871)
|
| End Program Hello
|
| ====
___________________________________________________________________
(page generated 2021-08-07 23:02 UTC)