zsh-workers
 help / color / mirror / code / Atom feed
* why do ceil/floor give the decimal dot?
@ 2015-05-14  0:32 Emanuel Berg
  2015-05-14  2:56 ` Bart Schaefer
  0 siblings, 1 reply; 17+ messages in thread
From: Emanuel Berg @ 2015-05-14  0:32 UTC (permalink / raw)
  To: zsh-workers

>From #zsh (incal == yours truly):

<incal> why do ceil/floor give the decimal dot?
        echo $(( floor(5) )) -> 5. Isn't that the
        whole "point" that you want an integer? I know
        I can get it with int but I thought I'd learn
        if there is a reason
        
<danielsh> incal, I suspect that's an oversight.
<danielsh> incal, it just uses the C floor() function,

<incal> danielsh: OK, that explains it but it is still
        an open question if it makes sense. Is there
        an interactive way to report "bugs" or
        suspected bugs in zsh like there is in Emacs
        with `report-emacs-bug'?
        
<danielsh> incal, best email the list
           zsh-workers@zsh.org

<incal> danielsh: is that in Gwene? I see
        gmane.comp.shells.zsh.user and
        gmane.comp.shells.zsh.devel - is it one of
        them? Or would they work still?
        
<danielsh> incal, either of those works (the lists are
           nested)

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14  0:32 why do ceil/floor give the decimal dot? Emanuel Berg
@ 2015-05-14  2:56 ` Bart Schaefer
  2015-05-14  3:29   ` Emanuel Berg
  0 siblings, 1 reply; 17+ messages in thread
From: Bart Schaefer @ 2015-05-14  2:56 UTC (permalink / raw)
  To: Emanuel Berg, zsh-workers

On May 14,  2:32am, Emanuel Berg wrote:
} Subject: why do ceil/floor give the decimal dot?
}
} >From #zsh (incal == yours truly):
} 
} <incal> why do ceil/floor give the decimal dot?
}         echo $(( floor(5) )) -> 5. Isn't that the
}         whole "point" that you want an integer? I know
}         I can get it with int but I thought I'd learn
}         if there is a reason
}         
} <danielsh> incal, I suspect that's an oversight.
} <danielsh> incal, it just uses the C floor() function,

It's not an oversight.  The doc says:

Most functions take floating point arguments and return a floating point
value.  However, any necessary conversions from or to integer type will
be performed automatically by the shell.  Apart from atan with a second
argument and the abs, int and float functions, all functions behave as
noted in the manual page for the corresponding C function [...]

So ciel and floor return float precisely and intentionally because the
C functions do so.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14  2:56 ` Bart Schaefer
@ 2015-05-14  3:29   ` Emanuel Berg
  2015-05-14  3:53     ` Lawrence Velázquez
  2015-05-14  4:04     ` Bart Schaefer
  0 siblings, 2 replies; 17+ messages in thread
From: Emanuel Berg @ 2015-05-14  3:29 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer <schaefer@brasslantern.com> writes:

> It's not an oversight. The doc says:
>
> Most functions take floating point arguments and
> return a floating point value. However, any
> necessary conversions from or to integer type will
> be performed automatically by the shell. Apart from
> atan with a second argument and the abs, int and
> float functions, all functions behave as noted in
> the manual page for the corresponding C function
> [...]
>
> So ciel and floor return float precisely and
> intentionally because the C functions do so.

Take a look at this [1] zsh:

    prefix-len () {
        local hosts=$1
        echo $(( 32 - int(ceil(log($hosts)/log(2))) ))
    }

without the integer conversion, the output for

    prefix-len 30

isn't 27, but "27."

[1] http://user.it.uu.se/~embe8573/conf/.zsh/web

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14  3:29   ` Emanuel Berg
@ 2015-05-14  3:53     ` Lawrence Velázquez
  2015-05-14  9:53       ` Peter Stephenson
  2015-05-14  4:04     ` Bart Schaefer
  1 sibling, 1 reply; 17+ messages in thread
From: Lawrence Velázquez @ 2015-05-14  3:53 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: zsh-workers

On May 13, 2015, at 11:29 PM, Emanuel Berg <embe8573@student.uu.se> wrote:

> Take a look at this [1] zsh:
> 
>    prefix-len () {
>        local hosts=$1
>        echo $(( 32 - int(ceil(log($hosts)/log(2))) ))
>    }
> 
> without the integer conversion, the output for
> 
>    prefix-len 30
> 
> isn't 27, but "27."

Yes, this is expected and correct. From "ARITHMETIC EVALUATION" in the
zshmisc(1) man page:

    Promotion of integer to floating point values is performed where
    necessary.

So:

- "ceil(log(30)/log(2))" returns floating-point "5."
- integer "32" is promoted to floating point "32."
- floating point "32." - floating point "5." = floating-point "27."

vq


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14  3:29   ` Emanuel Berg
  2015-05-14  3:53     ` Lawrence Velázquez
@ 2015-05-14  4:04     ` Bart Schaefer
  2015-05-14  9:12       ` Emanuel Berg
  1 sibling, 1 reply; 17+ messages in thread
From: Bart Schaefer @ 2015-05-14  4:04 UTC (permalink / raw)
  To: Emanuel Berg, zsh-workers

On May 14,  5:29am, Emanuel Berg wrote:
}
}     prefix-len () {
}         local hosts=$1
}         echo $(( 32 - int(ceil(log($hosts)/log(2))) ))
}     }
} 
} without the integer conversion, the output for
} 
}     prefix-len 30
} 
} isn't 27, but "27."

Yes, because as in most languages all integers in a mixed-type expression
are converted to floating point before the operation is carried out, so
$(( 32 - anyfloat )) becomes $(( 32. - anyfloat )) and results in a float.

If what you want to argue is that floating point values that happen to be
whole numbers should not print the trailing dot, that's another discussion.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14  4:04     ` Bart Schaefer
@ 2015-05-14  9:12       ` Emanuel Berg
  2015-05-14 17:54         ` Bart Schaefer
  0 siblings, 1 reply; 17+ messages in thread
From: Emanuel Berg @ 2015-05-14  9:12 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer <schaefer@brasslantern.com> writes:

> If what you want to argue is that floating point
> values that happen to be whole numbers should not
> print the trailing dot, that's another discussion.

You mean like this?

    $ printf "%d\n" $(( 7.5 + 0.5 ))
    8

No, I don't care what data type is used as long as

    1. ceil and floor return integers in the math
       sense (otherwise the function I just posted is
       is incorrect); and

    2. when the result is printed, it is printed as
       x (and not "x.") for an integer x, because
       otherwise I can't use that function in scripts
       and functions without removing the dot
       each time.

Or, do you think the "unbroken chain of floats"/"the
shell will deal with it"-approach instead should be
put to use, i.e. rolling with the punches, e.g.

    $ g () { return 6.0 }; g; b=$?; printf "%d\n" $b
    6

Is that what you are saying?

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14  3:53     ` Lawrence Velázquez
@ 2015-05-14  9:53       ` Peter Stephenson
  2015-05-14 21:38         ` Emanuel Berg
  0 siblings, 1 reply; 17+ messages in thread
From: Peter Stephenson @ 2015-05-14  9:53 UTC (permalink / raw)
  To: Emanuel Berg, zsh-workers

On Wed, 13 May 2015 23:53:53 -0400
Lawrence Velázquez <vq@larryv.me> wrote:
> - "ceil(log(30)/log(2))" returns floating-point "5."

... as noted, this is down to the C math library function returning
floating point.   It has to do this because it doesn't know the result
fits in an integer --- ceil(5e30) is a perfectly valid calculation.  See
the manual page.

So if you're happy it does fit, just convert to integer yourself.

pws


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14  9:12       ` Emanuel Berg
@ 2015-05-14 17:54         ` Bart Schaefer
  2015-05-18  8:39           ` Vincent Lefevre
  0 siblings, 1 reply; 17+ messages in thread
From: Bart Schaefer @ 2015-05-14 17:54 UTC (permalink / raw)
  To: zsh-workers; +Cc: Emanuel Berg

On May 14, 11:12am, Emanuel Berg wrote:
} Subject: Re: why do ceil/floor give the decimal dot?
}
} Bart Schaefer <schaefer@brasslantern.com> writes:
} 
} > If what you want to argue is that floating point
} > values that happen to be whole numbers should not
} > print the trailing dot, that's another discussion.
} 
} You mean like this?
} 
}     $ printf "%d\n" $(( 7.5 + 0.5 ))
}     8

No, I mean that looking at this:

torch% float X=27
torch% print $X
2.700000000e+01
torch% print $(( X ))
27.
torch% printf "%f\n" $X        
27.000000
torch% printf "%g\n" $X
27

One might wonder why there are four different representations of the
same number, and we could therefore discuss whether some of them should
be unified.  This is not the same discussion as whether they should be
converted to integers.

I don't imagine we have much leeway with printf, but ksh uses the "%g"
style for each of the first two cases instead of using scientific or
decimal notation.  I don't recall why zsh chose the other formats.

The problem changing the output reprsentations is that it potentially
changes the interpretation of $(( $X )) to be different from $(( X )).


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14  9:53       ` Peter Stephenson
@ 2015-05-14 21:38         ` Emanuel Berg
  2015-05-14 22:14           ` Lawrence Velázquez
  0 siblings, 1 reply; 17+ messages in thread
From: Emanuel Berg @ 2015-05-14 21:38 UTC (permalink / raw)
  To: zsh-workers

Peter Stephenson <p.stephenson@samsung.com> writes:

> So if you're happy it does fit, just convert to
> integer yourself.

Yeah, but you see what happened? On the one hand, you
shouldn't care what type it is and leave that to the
shell to work out. On the other hand, if you want
output that is manageable and that conforms with how
humans think of integers as well as the output of ceil
and floor, then you must convert to int manually!

I like the solution better to have the types all
floats (or whatever) and then use printf to make it
look the way you want.

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14 21:38         ` Emanuel Berg
@ 2015-05-14 22:14           ` Lawrence Velázquez
  2015-05-14 23:29             ` Emanuel Berg
                               ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Lawrence Velázquez @ 2015-05-14 22:14 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: zsh-workers

On May 14, 2015, at 5:38 PM, Emanuel Berg <embe8573@student.uu.se> wrote:

> I like the solution better to have the types all
> floats (or whatever) and then use printf to make it
> look the way you want.

You should use %g then (with appropriate precision) because %d does an
implicit conversion.

    % printf '%d\n' $(( 1e20 ))
    -9223372036854775808

    % printf '%g\n' $(( 1e20 ))
    1e+20

    % printf '%.30g\n' $(( 1e20 ))
    100000000000000000000

vq


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14 22:14           ` Lawrence Velázquez
@ 2015-05-14 23:29             ` Emanuel Berg
  2015-05-15  0:46             ` Oliver Kiddle
  2015-05-18  8:16             ` Vincent Lefevre
  2 siblings, 0 replies; 17+ messages in thread
From: Emanuel Berg @ 2015-05-14 23:29 UTC (permalink / raw)
  To: zsh-workers

Lawrence Velázquez <vq@larryv.me> writes:

>> I like the solution better to have the types all
>> floats (or whatever) and then use printf to make it
>> look the way you want.
>
> You should use %g then (with appropriate precision)
> because %d does an implicit conversion.
>
>     % printf '%d\n' $(( 1e20 ))
>     -9223372036854775808
>
>     % printf '%g\n' $(( 1e20 ))
>     1e+20
>
>     % printf '%.30g\n' $(( 1e20 ))
>     100000000000000000000

OK, case closed:

    prefix-len () {
        local hosts=$1
        local len=$(( 32 - ceil(log($hosts)/log(2)) ))
        printf "%g\n" $len
    }

    $ prefix-len 30
    27

Thanks everyone.

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14 22:14           ` Lawrence Velázquez
  2015-05-14 23:29             ` Emanuel Berg
@ 2015-05-15  0:46             ` Oliver Kiddle
  2015-05-15  1:07               ` Emanuel Berg
  2015-05-15  1:27               ` Bart Schaefer
  2015-05-18  8:16             ` Vincent Lefevre
  2 siblings, 2 replies; 17+ messages in thread
From: Oliver Kiddle @ 2015-05-15  0:46 UTC (permalink / raw)
  To: zsh-workers

Lawrence Velázquez wrote:
> 
>     % printf '%d\n' $(( 1e20 ))
>     -9223372036854775808

Note that if you're using zsh's builtin printf, parameters corresponding
to format specifiers such as %d are automatically evaluated in math
context. So you can just do:
  printf '%d\n' 1e20

It doesn't achieve much here but in some cases, this could avoid losing
precision.

Oliver


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-15  0:46             ` Oliver Kiddle
@ 2015-05-15  1:07               ` Emanuel Berg
  2015-05-15  1:27               ` Bart Schaefer
  1 sibling, 0 replies; 17+ messages in thread
From: Emanuel Berg @ 2015-05-15  1:07 UTC (permalink / raw)
  To: zsh-workers

Oliver Kiddle <okiddle@yahoo.co.uk> writes:

> Note that if you're using zsh's builtin printf,
> parameters corresponding to format specifiers such
> as %d are automatically evaluated in math context.
> So you can just do: printf '%d\n' 1e20
>
> It doesn't achieve much here but in some cases, this
> could avoid losing precision.

I'm using the builtin printf, not printf(1) (which
I have as /usr/bin/printf).

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-15  0:46             ` Oliver Kiddle
  2015-05-15  1:07               ` Emanuel Berg
@ 2015-05-15  1:27               ` Bart Schaefer
  1 sibling, 0 replies; 17+ messages in thread
From: Bart Schaefer @ 2015-05-15  1:27 UTC (permalink / raw)
  To: zsh-workers

On May 15,  2:46am, Oliver Kiddle wrote:
}
} Note that if you're using zsh's builtin printf, parameters corresponding
} to format specifiers such as %d are automatically evaluated in math
} context. So you can just do:
}   printf '%d\n' 1e20

Well, except that 1e20 is too large to fit in an integer.  Did you mean

    printf '%g\n" 1e20

??


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14 22:14           ` Lawrence Velázquez
  2015-05-14 23:29             ` Emanuel Berg
  2015-05-15  0:46             ` Oliver Kiddle
@ 2015-05-18  8:16             ` Vincent Lefevre
  2 siblings, 0 replies; 17+ messages in thread
From: Vincent Lefevre @ 2015-05-18  8:16 UTC (permalink / raw)
  To: Lawrence Velázquez; +Cc: Emanuel Berg, zsh-workers

On 2015-05-14 18:14:53 -0400, Lawrence Velázquez wrote:
> On May 14, 2015, at 5:38 PM, Emanuel Berg <embe8573@student.uu.se> wrote:
> 
> > I like the solution better to have the types all
> > floats (or whatever) and then use printf to make it
> > look the way you want.
> 
> You should use %g then (with appropriate precision) because %d does an
> implicit conversion.
> 
>     % printf '%d\n' $(( 1e20 ))
>     -9223372036854775808
> 
>     % printf '%g\n' $(( 1e20 ))
>     1e+20
> 
>     % printf '%.30g\n' $(( 1e20 ))
>     100000000000000000000

To output integers, it may be better to use %.0f because %g may output
the result with an exponent, or use a very large precision for %g so
that it wouldn't depend on the number to output, such as %.9999g (but
%.0f is shorter and simpler to understand). Now, if the user restricts
to the range where all integers are representable as floating point,
i.e. [-2^53,2^53], then %.16g is sufficient.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-14 17:54         ` Bart Schaefer
@ 2015-05-18  8:39           ` Vincent Lefevre
  2015-05-18  9:41             ` Mikael Magnusson
  0 siblings, 1 reply; 17+ messages in thread
From: Vincent Lefevre @ 2015-05-18  8:39 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-workers, Emanuel Berg

On 2015-05-14 10:54:26 -0700, Bart Schaefer wrote:
> No, I mean that looking at this:
> 
> torch% float X=27
> torch% print $X
> 2.700000000e+01
> torch% print $(( X ))
> 27.
> torch% printf "%f\n" $X        
> 27.000000
> torch% printf "%g\n" $X
> 27
> 
> One might wonder why there are four different representations of the
> same number, and we could therefore discuss whether some of them should
> be unified.  This is not the same discussion as whether they should be
> converted to integers.

Concerning the accuracy:

ypig% float x=$((1./3))
ypig% print $x
3.333333333e-01
ypig% print $((x))
0.33333333333333331
ypig% printf "%f\n" $x
0.333333
ypig% printf "%g\n" $x
0.333333

The last two are specified by C, and I suppose that $((x)) gives full
accuracy, i.e. if the decimal number is re-read as a floating-point
value, the original value must be recovered exactly.

Concerning the first one, I wonder why there are "typeset -E" (default
for "float" as used above) and "typeset -F". The way a value is output
shouldn't come from its declaration. IMHO, there should be a single
floating-point datatype, not one for each output format.

BTW, there is a bug in zsh 5.0.7:

ypig% typeset -F 3 x=$((17))
ypig% print $x
17.000
ypig% typeset -F 2 x=$((17))
ypig% print $x              
17.00
ypig% typeset -F 1 x=$((17))
typeset: invalid base (must be 2 to 36 inclusive): 1

It is not a base here.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: why do ceil/floor give the decimal dot?
  2015-05-18  8:39           ` Vincent Lefevre
@ 2015-05-18  9:41             ` Mikael Magnusson
  0 siblings, 0 replies; 17+ messages in thread
From: Mikael Magnusson @ 2015-05-18  9:41 UTC (permalink / raw)
  To: zsh workers

On Mon, May 18, 2015 at 10:39 AM, Vincent Lefevre <vincent@vinc17.net> wrote:
> BTW, there is a bug in zsh 5.0.7:
>
> ypig% typeset -F 3 x=$((17))
> ypig% print $x
> 17.000
> ypig% typeset -F 2 x=$((17))
> ypig% print $x
> 17.00
> ypig% typeset -F 1 x=$((17))
> typeset: invalid base (must be 2 to 36 inclusive): 1
>
> It is not a base here.

Fortunately I fixed that bug a few weeks ago.

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2015-05-18  9:41 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-14  0:32 why do ceil/floor give the decimal dot? Emanuel Berg
2015-05-14  2:56 ` Bart Schaefer
2015-05-14  3:29   ` Emanuel Berg
2015-05-14  3:53     ` Lawrence Velázquez
2015-05-14  9:53       ` Peter Stephenson
2015-05-14 21:38         ` Emanuel Berg
2015-05-14 22:14           ` Lawrence Velázquez
2015-05-14 23:29             ` Emanuel Berg
2015-05-15  0:46             ` Oliver Kiddle
2015-05-15  1:07               ` Emanuel Berg
2015-05-15  1:27               ` Bart Schaefer
2015-05-18  8:16             ` Vincent Lefevre
2015-05-14  4:04     ` Bart Schaefer
2015-05-14  9:12       ` Emanuel Berg
2015-05-14 17:54         ` Bart Schaefer
2015-05-18  8:39           ` Vincent Lefevre
2015-05-18  9:41             ` Mikael Magnusson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).