Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:122989 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 4BD541A009C for ; Fri, 5 Apr 2024 22:52:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1712357594; bh=PPRn1JHUzDPNeCgGki4tl5KQ8HB4ptEPbgh7WOM5vgo=; h=Date:Subject:To:References:From:In-Reply-To:From; b=Jj95Ll+OGQfLz+VK5cEm/UelYD91cAFZoOQ8f98Tec++6EDcXI+XwAB6uxahzmOU1 yYZyFRISWBICY1SjZxt4QMFpZLQymeRGjdTaj3vfjzV0zAZhYDDR2Dqo3XOD/QcJ5/ Z/HwzrFmkE1VyddErTNJeey16CJ5Hw2Jd5S2rbaTPaMeVg8X79L6V4fexjuV49KjaK m3/IMziepv+s3cy6O1mXJd7f+un2tCNu/wT2HIKyUxsMkV1K5ULpaU5Pi3sUGrm0d4 VoZ8TrYdte88p2lUQun47ysbHP5ZlW1Fk2BhKCpaseKeK+P7xObgmpFT/F8U91ZCnn Ibw90BiiY0Lig== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B529A180074 for ; Fri, 5 Apr 2024 22:53:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from wfhigh5-smtp.messagingengine.com (wfhigh5-smtp.messagingengine.com [64.147.123.156]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 5 Apr 2024 22:53:12 +0000 (UTC) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailfhigh.west.internal (Postfix) with ESMTP id BEC0D18000E5 for ; Fri, 5 Apr 2024 18:52:41 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Fri, 05 Apr 2024 18:52:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rwec.co.uk; h=cc :content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm2; t=1712357561; x=1712443961; bh=j24nCOvUtH ymFyJRwVHYl2hMN6crDkGKsYR9+JP972A=; b=jQIuwvnlaiyt0Lh8lb5reNObpU DS/JoTXDJSs74eZ9nrybvqD2yvERkJKtKoRczC7BNZpVkAC5K1OS/xQsRyRnXKx5 ccE4oI8OimLPGzNwh/lauEqZrOhj1FxZXXksh7VNLcNE//lIdGHVl7HegwuZfLw/ 295vsh4IAHKthqi/09i5VGvYKh8JY7pUGI2bDtD4d5SyL5Ce0m96YSQPnGZoW5Oi EsWN060BuOyTf1+2s0mfdVNNAPnQSzy1XNIXJ6IQI/KqDouLZ+nHO9SwE9oIca9f XdlOa1g33vIVtn/0PpW83Mg6T3BA8yDfxYQgUf9N8TnPppVODzUW8Zmx84Yg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; t=1712357561; x=1712443961; bh=j24nCOvUtHymFyJRwVHYl2hMN6cr DkGKsYR9+JP972A=; b=QGCKcNBOqCudrezIOZzfy/mzlp4AevEe7TuCRKuPJXSu ht8NCwH8/db5knmjVKQdlqvzw0WyAl4EZXMEKk9d4I8m+1LMUWqbhAJgEn/Zykqh /NBqiHqCQPTv4fBFQrh4IcJoHTeMfjPXeuCuQBQ6BH0hqCjP0XbpQLwoD1raB1/P eNXg9jvu4qXE7pZxRd2A+Vir6vdCFDT1pUPX32q19kt13+Zcy9eioO6gQtOlIBY+ w30Mdm4VnWdoGDBfRJoKn2mZoUTc5+jpIMpJ8cGQZRQzeCYmdN7oWLxc8PsfujzY ImGE5+l2vI0vy7u4G+HOKvl85X3yXEbfo5oq7SOqRA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrudeguddgudehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpegtkfffgggfuffvfhfhjgesrgdtre ertddvjeenucfhrhhomhepfdftohifrghnucfvohhmmhhinhhsucglkffoufhorfgnfdcu oehimhhsohhprdhphhhpsehrfigvtgdrtghordhukheqnecuggftrfgrthhtvghrnhephf elkeeufedvheefgfetveehteeggfduvdfftddugfdvieetjeefkedtteejvdfhnecuffho mhgrihhnpehmohhnvgihphhhphdrohhrghdpghhithhhuhgsrdgtohhmnecuvehluhhsth gvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepihhmshhophdrphhhphes rhifvggtrdgtohdruhhk X-ME-Proxy: Feedback-ID: id5114917:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Fri, 5 Apr 2024 18:52:40 -0400 (EDT) Content-Type: multipart/alternative; boundary="------------7PngVxyl3eG3GjXZQ0dagxlE" Message-ID: <3c74f433-be6b-4f20-beb0-f09db2fb39b6@rwec.co.uk> Date: Fri, 5 Apr 2024 23:52:35 +0100 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type To: internals@lists.php.net References: <18c42fdbb30.2831.17a3710df6d58f02ca570cc47e197a63@interi.co> <9dfdd88a-f840-4933-b26b-8149a4381246@rwec.co.uk> Content-Language: en-GB In-Reply-To: From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]") This is a multi-part message in MIME format. --------------7PngVxyl3eG3GjXZQ0dagxlE Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 04/04/2024 23:31, Jordan LeDoux wrote: > > Well, firstly most of the financial applications that I've worked in > (I work for a firm that writes accounting software right now) do not > calculate intermediate steps like this with fixed precision, or even > have an interest in doing so. My background is in e-commerce (specifically, travel) rather than finance. In that context, it's common to have a single-step operation like "per_person_price equals total_price divided by number of passengers" where both per_person_price and total_price are going to be expressed with the same accuracy. The top two results for "money" on Packagist are https://www.moneyphp.org/ and https://github.com/brick/money both of which take this general model: the scale of values is fixed, and every operation that might produce fractions of that requires a rounding mode. > Truly "fixed-precision" is not something that decimal should even try > to be, in my opinion. The use cases where you CANNOT simply round the > result at the end to fit your display output or your storage location > are very minimal. In that case, why do we need to think about the scale or precision of a decimal at all? What would the syntax 1.234_d3 do differently from 1.234_d? > I mean, what you are describing is how such OBJECTS are designed in > other languages like Python, but not scalars. I don't see any connection at all between what I'm describing and objects. I'm talking about what operations make sense on a particular data type, regardless of how that data type is implemented. To be honest, I'm not really sure what "scalar" means in this context. In PHP, we call strings "scalars" because they're neither "arrays" nor "objects"; but none of those have definitions which are universal to other languages. > This kind of precision restriction isn't something you would place on > an individual value, it's something you would place on all > calculations. That's why in Python this is done with a global runtime > setting using `getContext().perc` and `getContext().rounding`. A > particular value having a precision of X doesn't imply anything > concrete about a calculation that uses that value necessarily. Global settings avoid needing extra parameters to each operation, but don't really work for the use case I'm describing: different currencies have different "natural" scale, e.g. Japanese Yen have a scale of 0 (no fractional Yen), Bitcoin has a scale of 8 (100 million satoshis in 1 bitcoin).  A program dealing with multiple currencies will want to assign a different scale to different values. > Maybe we're just not understanding each other. Are you opposed to the > idea of doing this as a scalar? Not at all; my first examples used method syntax, because I was basing them on https://github.com/brick/money In my last e-mail, I also gave examples using normal function syntax. What I'm saying is that $x / 2 doesn't have a good answer if $x is a fixed-precision number which can't be divided by 2 without exceeding that precision. You need a third operand, the rounding mode, so you can't write it as a binary operator, and need some kind of function like decimal_div(decimal $dividend, int|decimal $divisor, RoundingMode $roundingMode). How you implement "decimal" doesn't change that at all. Regards, -- Rowan Tommins [IMSoP] --------------7PngVxyl3eG3GjXZQ0dagxlE Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit
On 04/04/2024 23:31, Jordan LeDoux wrote:

Well, firstly most of the financial applications that I've worked in (I work for a firm that writes accounting software right now) do not calculate intermediate steps like this with fixed precision, or even have an interest in doing so.


My background is in e-commerce (specifically, travel) rather than finance. In that context, it's common to have a single-step operation like "per_person_price equals total_price divided by number of passengers" where both per_person_price and total_price are going to be expressed with the same accuracy.

The top two results for "money" on Packagist are https://www.moneyphp.org/ and https://github.com/brick/money both of which take this general model: the scale of values is fixed, and every operation that might produce fractions of that requires a rounding mode.


Truly "fixed-precision" is not something that decimal should even try to be, in my opinion. The use cases where you CANNOT simply round the result at the end to fit your display output or your storage location are very minimal.


In that case, why do we need to think about the scale or precision of a decimal at all? What would the syntax 1.234_d3 do differently from 1.234_d?


I mean, what you are describing is how such OBJECTS are designed in other languages like Python, but not scalars.


I don't see any connection at all between what I'm describing and objects. I'm talking about what operations make sense on a particular data type, regardless of how that data type is implemented.

To be honest, I'm not really sure what "scalar" means in this context. In PHP, we call strings "scalars" because they're neither "arrays" nor "objects"; but none of those have definitions which are universal to other languages.


This kind of precision restriction isn't something you would place on an individual value, it's something you would place on all calculations. That's why in Python this is done with a global runtime setting using `getContext().perc` and `getContext().rounding`. A particular value having a precision of X doesn't imply anything concrete about a calculation that uses that value necessarily.


Global settings avoid needing extra parameters to each operation, but don't really work for the use case I'm describing: different currencies have different "natural" scale, e.g. Japanese Yen have a scale of 0 (no fractional Yen), Bitcoin has a scale of 8 (100 million satoshis in 1 bitcoin).  A program dealing with multiple currencies will want to assign a different scale to different values.


Maybe we're just not understanding each other. Are you opposed to the idea of doing this as a scalar?


Not at all; my first examples used method syntax, because I was basing them on https://github.com/brick/money In my last e-mail, I also gave examples using normal function syntax.

What I'm saying is that $x / 2 doesn't have a good answer if $x is a fixed-precision number which can't be divided by 2 without exceeding that precision. You need a third operand, the rounding mode, so you can't write it as a binary operator, and need some kind of function like decimal_div(decimal $dividend, int|decimal $divisor, RoundingMode $roundingMode). How you implement "decimal" doesn't change that at all.


Regards,

-- 
Rowan Tommins
[IMSoP]
--------------7PngVxyl3eG3GjXZQ0dagxlE--