|
From: theozh <th...@gm...> - 2017-11-14 21:39:40
|
as described in gnuplot help, gnuplot does integer divison if the dividend and the divisors are integers.
As a normal user, you don't expect this and you will learn about this "pitfall" when you're wondering why you get wrong plotting results (or if you read the manual from the beginning to the end and will stumble across it).
How to force a floating point division with two integer variables, e.g. in loops?
The only way I found is to multiply the first number by 1.0
Is this really the way to go?
Example:
do for [i=1:6] {
do for [j=1:6] { print sprintf("%g\t%g",i/j,i*1./j) }
}
Isn't there maybe a way to set a flag to always use floating point divison?
|
|
From: Ethan M. <eam...@gm...> - 2017-11-14 21:56:04
|
On Tue, Nov 14, 2017 at 1:39 PM, theozh <th...@gm...> wrote:
> as described in gnuplot help, gnuplot does integer divison if the dividend and the divisors are integers.
> As a normal user, you don't expect this
[shrug] integer division is "normal" for most programming and
scripting languages.
> and you will learn about this "pitfall" when you're wondering why you get wrong plotting results (or if you read the manual from the beginning to the end and will stumble across it).
>
> How to force a floating point division with two integer variables, e.g. in loops?
If you need to force a variable to be a real number, use real(var).
Conversely if you need an integer, use int(var).
> The only way I found is to multiply the first number by 1.0
> Is this really the way to go?
>
> Example:
>
> do for [i=1:6] {
> do for [j=1:6] { print sprintf("%g\t%g",i/j,i*1./j) }
> }
>
> Isn't there maybe a way to set a flag to always use floating point divison?
print real(i) / real(j)
Ethan
|
|
From: theozh <th...@gm...> - 2017-11-14 22:20:01
|
Thanks Ethan, I knew the int() function but didn't know about the real() function. I thought this is for extracting the real part of complex numbers, but obviously it can also be used to convert an integer number to a real number. > [shrug] integer division is "normal" for most programming and > scripting languages. [ahem]... then the few languages I know a little bit (Perl, Python, Pascal,... ) are not "normal" ;-) What worries me a bit is: Quote help: "The result of division of a negative integer by a positive one may vary among compilers. Try a test like "print -5/2" to determine if your system chooses -2 or -3 as the answer." Well, as long as I am working only on my system I should know what I will get ;-). |
|
From: Ethan M. <eam...@gm...> - 2017-11-14 23:07:35
|
On Tue, Nov 14, 2017 at 2:19 PM, theozh <th...@gm...> wrote: > Thanks Ethan, > I knew the int() function but didn't know about the real() function. I thought this is for extracting the real part of complex numbers, but obviously it can also be used to convert an integer number to a real number. > >> [shrug] integer division is "normal" for most programming and >> scripting languages. > [ahem]... then the few languages I know a little bit (Perl, Python, Pascal,... ) are not "normal" ;-) I think you are mis-remembering > stonelion [163] python > Python 2.7.13 (default, Jan 28 2017, 17:29:29) > [GCC 5.4.0] on linux2 > Type "help", "copyright", "credits" or "license" for more information. > >>> print 5/2 > 2 > >>> > > Perl being perl, you have your choice :-) Although it is true that perl defaults to floating division, it is recommended to place the "use integer" pragma at the start of any program that cares. stonelion [164] perl > use integer; > print 5/2, "\n"; > 2 > > Pascal (ah nostalgia...) it's been years. I no longer remember, and I don't have a Pascal compiler on my current machines to try it. > What worries me a bit is: > Quote help: > "The result of division of a negative integer by a positive one may vary among compilers. Try a test like "print -5/2" to determine if your system chooses -2 or -3 as the answer." I suspect that statement dates all the way back to 1980something, and refers to compilers or computer architectures from last century. C99 compliance guarantees truncation towards zero. (But C89 did not, so yes at the time gnuplot was first written it made sense to worry about this). As a side note - people contributing code to gnuplot recently often assume that use of C99 features is OK. We may want to require use of a C99 compliant complier in the future, but so far the gnuplot coding guidelines and installation instructions don't say that. If we add that caveat for 5.3, I will remove the caution you point to in the docs. > Well, as long as I am working only on my system I should know what I will get ;-). Anyhow, using real(variable) will force floating point arithmetic if you need that. |
|
From: David K. <da...@gn...> - 2017-11-14 23:15:34
|
Ethan Merritt <eam...@gm...> writes: > Pascal (ah nostalgia...) it's been years. I no longer remember, and I > don't have a Pascal > compiler on my current machines to try it. Pascal has "div" and "mod" operators if you want integer results. -- David Kastrup |
|
From: David K. <da...@gn...> - 2017-11-14 23:13:43
|
Ethan Merritt <eam...@gm...> writes: > On Tue, Nov 14, 2017 at 1:39 PM, theozh <th...@gm...> wrote: >> as described in gnuplot help, gnuplot does integer divison if the >> dividend and the divisors are integers. >> As a normal user, you don't expect this > > [shrug] integer division is "normal" for most programming and > scripting languages. Octave: 0.50000 Guile: 1/2 awk: 0.5 Perl: 0.5 Lua: 0.5 Python: 0 bc: 0 Bash: 0 Pascal: 0.5 Fortran: 0 Now I'll grant you Fortran and Python. The rest either gives 0.5 or is not intended for floating point calculations anyway. Arguably Octave is the most relevantly similar in scope. -- David Kastrup |
|
From: Ethan M. <eam...@gm...> - 2017-11-14 23:43:00
|
On Tue, Nov 14, 2017 at 3:13 PM, David Kastrup <da...@gn...> wrote: > Ethan Merritt <eam...@gm...> writes: > > > On Tue, Nov 14, 2017 at 1:39 PM, theozh <th...@gm...> wrote: > >> as described in gnuplot help, gnuplot does integer divison if the > >> dividend and the divisors are integers. > >> As a normal user, you don't expect this > > > > [shrug] integer division is "normal" for most programming and > > scripting languages. > > Octave: 0.50000 Guile: 1/2 > awk: 0.5 > Perl: 0.5 > Lua: 0.5 > Python: 0 > bc: 0 > Bash: 0 > Pascal: 0.5 > Fortran: 0 > > Now I'll grant you Fortran and Python. The rest either gives 0.5 or is > not intended for floating point calculations anyway. > You left out the most relevant of all. Gnuplot is written in C and uses C language code for internal and user-visible evaluations. [now I'm nit-picking...] Lua doesn't have integer variables, so there the question is moot. Ruby: stonelion [186] ruby print 1/2, "\n" 0 Ethan > Arguably Octave is the most relevantly similar in scope. > > -- > David Kastrup > > ------------------------------------------------------------ > ------------------ > Check out the vibrant tech community on one of the world's most > engaging tech sites, Slashdot.org! http://sdm.link/slashdot > _______________________________________________ > gnuplot-info mailing list > gnu...@li... > Membership management via: https://lists.sourceforge.net/ > lists/listinfo/gnuplot-info > |
|
From: David K. <da...@gn...> - 2017-11-15 00:06:20
|
Ethan Merritt <eam...@gm...> writes: > On Tue, Nov 14, 2017 at 3:13 PM, David Kastrup <da...@gn...> wrote: > >> Ethan Merritt <eam...@gm...> writes: >> >> > On Tue, Nov 14, 2017 at 1:39 PM, theozh <th...@gm...> wrote: >> >> as described in gnuplot help, gnuplot does integer divison if the >> >> dividend and the divisors are integers. >> >> As a normal user, you don't expect this >> > >> > [shrug] integer division is "normal" for most programming and >> > scripting languages. >> >> Octave: 0.50000 > > Guile: 1/2 >> awk: 0.5 >> Perl: 0.5 >> Lua: 0.5 >> Python: 0 >> bc: 0 >> Bash: 0 >> Pascal: 0.5 >> Fortran: 0 >> >> Now I'll grant you Fortran and Python. The rest either gives 0.5 or is >> not intended for floating point calculations anyway. >> > > You left out the most relevant of all. > Gnuplot is written in C and uses C language code for internal and > user-visible evaluations. The implementation is completely irrelevant for the semantics (most scripting languages are implemented in C), and Gnuplot has operators like ** eq ne . > [now I'm nit-picking...] > > Lua doesn't have integer variables, so there the question is moot. Uh what? Octave does not have integer variables either because it is intended for numerical work. As is Gnuplot. Really, it's completely irrelevant what Gnuplot is implemented in. The question is what its application domain is. The user has nothing to gain from getting some technical analogy to the implementation language as an explanation for tripping him up. C is prone to crashes due to its memory access and allocation semantics, but that does not mean that it's Gnuplot's duty to give the user ways to crash the machine. At any rate, we are talking about decisions that have managed to stick around for decades, similar to % only being permitted for integers, as if there never was a need to, say, wrap a value in the 0..2pi domain or even calculate 420.5 % 360 for the sake of degrees. The main reason appears to me to rub the users' noses in the programmers' superior knowledge of C semantics. Gnuplot does not use a C parser so there is no inherent reason to prescribe C semantics. -- David Kastrup |
|
From: David K. <da...@gn...> - 2017-11-15 11:34:14
|
Ethan Merritt <eam...@gm...> writes: > [now I'm nit-picking...] > > Lua doesn't have integer variables, so there the question is moot. That nit, by the way, is dead. dak@lola:/usr/local/tmp/lilypond$ lua5.3 Lua 5.3.3 Copyright (C) 1994-2016 Lua.org, PUC-Rio > =math.type(4.0) float > =math.type(4) integer > -- David Kastrup |
|
From: Tait <gnu...@t4...> - 2017-11-15 00:37:07
|
> >> as described in gnuplot help, gnuplot does integer divison if the > >> dividend and the divisors are integers. > >> As a normal user, you don't expect this > > > > [shrug] integer division is "normal" for most programming and > > scripting languages. > > Octave: 0.50000 > Guile: 1/2 > awk: 0.5 > Perl: 0.5 > Lua: 0.5 > Python: 0 > bc: 0 > Bash: 0 > Pascal: 0.5 > Fortran: 0 > > Now I'll grant you Fortran and Python. The rest either gives 0.5 or is > not intended for floating point calculations anyway. > > Arguably Octave is the most relevantly similar in scope. It's worth mentioning that Python has changed this behavior. In Python2, division defaults to integer-division and 1/2 is 0. Starting with Python3 (which in my experience is used everywhere except niche applications by now) "true" division applies, meaning types are auto-promoted such that 1/2 is 0.5. I'd say integer division is gradually becoming an anachronism, and the new trend seems to be not just fixed floating-point but full rational-number support or arbitrary- (even infinite-) precision calculations, to avoid frustrating behaviors like ceil(900e-7/12e-7) => 76. |
|
From: Ethan M. <eam...@gm...> - 2017-11-15 01:03:29
|
On Tue, Nov 14, 2017 at 4:38 PM, Tait <gnu...@t4...> wrote:
>
> It's worth mentioning that Python has changed this behavior. In
> Python2, division defaults to integer-division and 1/2 is 0.
> Starting with Python3 (which in my experience is used everywhere
> except niche applications by now) "true" division applies,
> meaning types are auto-promoted such that 1/2 is 0.5.
>
My experience differs. I have seen hardly a sign of Python3.
Then again, probably every single application in my field counts as "niche".
Either way I really, really don't think we want to use Python as a guide.
I'd say integer division is gradually becoming an anachronism,
> and the new trend seems to be not just fixed floating-point but
> full rational-number support or arbitrary- (even infinite-)
> precision calculations, to avoid frustrating behaviors like
> ceil(900e-7/12e-7) => 76.
>
There you intrigue me. I have a patch series queued that adds 64-bit
integer arithmetic with full overflow handling everywhere. Would it indeed
be feasible to similarly upgrade the floating point evaluation code to
provide more graceful handling of very large numbers?
The int64 conversion was surprisingly easy so I can believe that
modernizing the floating point would also be straightforward.
But I wouldn't know where to start. Do you have suggestions?
Ethan
|
|
From: Tait <gnu...@t4...> - 2017-11-15 01:42:55
|
> > I'd say integer division is gradually becoming an anachronism, > > and the new trend seems to be not just fixed floating-point but > > full rational-number support or arbitrary- (even infinite-) > > precision calculations, to avoid frustrating behaviors like > > ceil(900e-7/12e-7) => 76. > > There you intrigue me. I have a patch series queued that adds 64-bit > integer arithmetic with full overflow handling everywhere. Would it indeed > be feasible to similarly upgrade the floating point evaluation code to > provide more graceful handling of very large numbers? > The int64 conversion was surprisingly easy so I can believe that > modernizing the floating point would also be straightforward. > But I wouldn't know where to start. Do you have suggestions? That particular example will "misbehave" even with 64b doubles (or at least it did in my test, which is why I used that particular example). But in general, the only reason I see not to convert from float to double is that some platforms wouldn't have built-in double support. I don't work on esoteric platforms anymore, and obviously Win/Linux/Mac all handle double fine. |
|
From: David K. <da...@gn...> - 2017-11-15 01:48:13
|
Tait <gnu...@t4...> writes: >> > I'd say integer division is gradually becoming an anachronism, >> > and the new trend seems to be not just fixed floating-point but >> > full rational-number support or arbitrary- (even infinite-) >> > precision calculations, to avoid frustrating behaviors like >> > ceil(900e-7/12e-7) => 76. >> >> There you intrigue me. I have a patch series queued that adds 64-bit >> integer arithmetic with full overflow handling everywhere. Would it indeed >> be feasible to similarly upgrade the floating point evaluation code to >> provide more graceful handling of very large numbers? >> The int64 conversion was surprisingly easy so I can believe that >> modernizing the floating point would also be straightforward. >> But I wouldn't know where to start. Do you have suggestions? > > That particular example will "misbehave" even with 64b doubles > (or at least it did in my test, which is why I used that > particular example). But in general, the only reason I see not > to convert from float to double is that some platforms wouldn't > have built-in double support. Since historically double had been the _only_ floating point _expression_ format in K&R C (as opposed to floating point storage format that could be just float), platforms without built-in double support would be really peculiar once using them for C became a mainstream choice. -- David Kastrup |
|
From: Ethan A M. <EAM...@gm...> - 2017-11-15 02:45:34
|
On Wednesday, 15 November 2017 01:44:04 you wrote: > > > I'd say integer division is gradually becoming an anachronism, > > > and the new trend seems to be not just fixed floating-point but > > > full rational-number support or arbitrary- (even infinite-) > > > precision calculations, to avoid frustrating behaviors like > > > ceil(900e-7/12e-7) => 76. > > > > There you intrigue me. I have a patch series queued that adds 64-bit > > integer arithmetic with full overflow handling everywhere. Would it indeed > > be feasible to similarly upgrade the floating point evaluation code to > > provide more graceful handling of very large numbers? > > The int64 conversion was surprisingly easy so I can believe that > > modernizing the floating point would also be straightforward. > > But I wouldn't know where to start. Do you have suggestions? > > That particular example will "misbehave" even with 64b doubles > (or at least it did in my test, which is why I used that > particular example). It does not misbehave here in gnuplot (linux x86-64 platform) I tried a few larger exponents at random, up to ceil(900e-101/12e-101), without tripping an error. Is there some particular pattern that is prone to error? > But in general, the only reason I see not > to convert from float to double is that some platforms wouldn't > have built-in double support. Gnuplot has used (double) everywhere since 2011, when we dropped support for 16-bit Windows. The only exception is that when reading in binary matrix files, the matrix is stored as (float). I don't know why that was, but it's on my list of things to fix in 5.3 > I don't work on esoteric platforms > anymore, and obviously Win/Linux/Mac all handle double fine. Exactly. Ethan |
|
From: Tait <gnu...@t4...> - 2017-11-15 02:32:19
|
> > > > ceil(900e-7/12e-7) => 76.
> > > ...
> > That particular example will "misbehave" even with 64b doubles
> > (or at least it did in my test, which is why I used that
> > particular example).
>
> It does not misbehave here in gnuplot (linux x86-64 platform)
>
> I tried a few larger exponents at random, up to
> ceil(900e-101/12e-101), without tripping an error.
> Is there some particular pattern that is prone to error?
Sorry; I meant it misbehaves in a dumb little C++
program I was using to test, not in gnuplot.
#include <iostream>
#include <ios>
#include <iomanip>
#include <cmath>
int main() {
double num1 = 900e-7;
double num2 = 12e-7;
std::cout << std::setprecision(30) << std::fixed
<< num1 << std::endl
<< num2 << std::endl
<< num1/num2 << std::endl
<< std::ceil(num1/num2) << std::endl;
return 0;
}
Although as you say, it doesn't go to 76 in gnuplot,
which makes me wonder why it behaves differently.
|