digitalmars.D.learn - Convert double to long if lossless
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (23/23) Jan 19 2021 I want to convert a double to a long if conversion is lossless
- Steven Schveighoffer (4/30) Jan 19 2021 Use a cast instead.
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (4/6) Jan 19 2021 Ahh, good point.
- drug (5/13) Jan 19 2021 don't forget to check by std.math.isFinite before casting
- drug (2/17) Jan 19 2021 *fractional part
- =?UTF-8?Q?Ali_=c3=87ehreli?= (4/5) Jan 19 2021 Luckily, we already have a helper in Phobos:
- drug (37/47) Jan 19 2021 That makes life simpler, thanks for sharing this:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (3/5) Jan 19 2021 I think it would be a useful improvement.
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (2/3) Jan 19 2021 Indeed. Maybe Ilya could help out adding this to dmd.
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (14/15) Jan 19 2021 Doesn't this pattern already cover all possible cases of `value`
- =?UTF-8?Q?Ali_=c3=87ehreli?= (5/8) Jan 19 2021 d?
- drug (6/23) Jan 20 2021 Sure. You don't even need to use isFinite like I wrote above because
- kdevel (16/19) Jan 19 2021 And then? I mean: What do you want to do with the long what could
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (5/8) Jan 19 2021 Motivated question.
I want to convert a double to a long if conversion is lossless (without fractional part, non-nan, non-inf, within long-range, etc). I currently have void foo() { const double value = 10.1; try { import std.conv : to; const lvalue = value.to!long; if (lvalue == value) { writeln("lvalue:", lvalue); return; } } catch (Exception e) {} writeln("value:", value); } Can this be improved? For instance how do I check if a float/double/real has a fractional part and avoid entering try-catch for those cases?
Jan 19 2021
On 1/19/21 6:42 AM, Per Nordlöw wrote:I want to convert a double to a long if conversion is lossless (without fractional part, non-nan, non-inf, within long-range, etc). I currently have void foo() { const double value = 10.1; try { import std.conv : to; const lvalue = value.to!long; if (lvalue == value) { writeln("lvalue:", lvalue); return; } } catch (Exception e) {} writeln("value:", value); } Can this be improved? For instance how do I check if a float/double/real has a fractional part and avoid entering try-catch for those cases?Use a cast instead. const lvalue = cast(long)value; -Steve
Jan 19 2021
On Tuesday, 19 January 2021 at 13:36:58 UTC, Steven Schveighoffer wrote:Use a cast instead. const lvalue = cast(long)value;Ahh, good point. Followd by a compare of the original value I presume.
Jan 19 2021
On 1/19/21 4:48 PM, Per Nordlöw wrote:On Tuesday, 19 January 2021 at 13:36:58 UTC, Steven Schveighoffer wrote:don't forget to check by std.math.isFinite before casting Another (low level) way is to shift mantissa left by exponent value. If the remainder equals to zero then no fractal part was encoded in the floating value.Use a cast instead. const lvalue = cast(long)value;Ahh, good point. Followd by a compare of the original value I presume.
Jan 19 2021
On 1/19/21 5:04 PM, drug wrote:On 1/19/21 4:48 PM, Per Nordlöw wrote:*fractional partOn Tuesday, 19 January 2021 at 13:36:58 UTC, Steven Schveighoffer wrote:don't forget to check by std.math.isFinite before casting Another (low level) way is to shift mantissa left by exponent value. If the remainder equals to zero then no fractal part was encoded in the floating value.Use a cast instead. const lvalue = cast(long)value;Ahh, good point. Followd by a compare of the original value I presume.
Jan 19 2021
On 1/19/21 6:04 AM, drug wrote:Another (low level) way is to shift mantissa left by exponent value.Luckily, we already have a helper in Phobos: https://dlang.org/phobos/std_bitmanip.html#FloatRep Ali
Jan 19 2021
On 1/19/21 6:50 PM, Ali Çehreli wrote:On 1/19/21 6:04 AM, drug wrote: > Another (low level) way is to shift mantissa left by exponent value. Luckily, we already have a helper in Phobos: https://dlang.org/phobos/std_bitmanip.html#FloatRep AliThat makes life simpler, thanks for sharing this: ```D import std; void main() { auto valueRange = [ 10.000000000000001, 10.0000000000000001, // in fact this is just 10.0 ]; foreach(value; valueRange) { auto dr = DoubleRep(value); const hasFractional = !!(dr.fraction << (dr.exponent-1023+12)); writefln("has `%.18f` fractional part: %s", value, hasFractional); } } ``` but I think that casting to long and comparing it to the value is easier to understand and more portable: ```D import std; void main() { auto valueRange = [ 10.000000000000001, 10.0000000000000001, // in fact this is 10.0 ]; foreach(value; valueRange) { const hasFractional = (value != cast(long)value); writefln("has `%.18f` fractional part: %s", value, hasFractional); } } ``` P.S. shouldn't compiler emit the error if a literal can't be represented lossless?
Jan 19 2021
On 1/19/21 8:14 AM, drug wrote:P.S. shouldn't compiler emit the error if a literal can't be represented lossless?I think it would be a useful improvement. Ali
Jan 19 2021
On Tuesday, 19 January 2021 at 17:03:53 UTC, Ali Çehreli wrote:I think it would be a useful improvement.Indeed. Maybe Ilya could help out adding this to dmd.
Jan 19 2021
On Tuesday, 19 January 2021 at 16:14:17 UTC, drug wrote:Doesn't this pattern already cover all possible cases of `value` needed? void f(double value) { auto lvalue = cast(long)value; if (lvalue == value) // `value` lacks fraction and in range [long.min .. long.max] { // use long lvalue return; } // use double value }https://dlang.org/phobos/std_bitmanip.html#FloatRep
Jan 19 2021
On 1/19/21 10:28 AM, Per Nordl=C3=B6w wrote:On Tuesday, 19 January 2021 at 16:14:17 UTC, drug wrote:d? I think so. I just remembered FloatRep as a cleaner tool compared to=20 shifting bits explicitly. AliDoesn't this pattern already cover all possible cases of `value` neede=https://dlang.org/phobos/std_bitmanip.html#FloatRep
Jan 19 2021
On 1/19/21 9:28 PM, Per Nordlöw wrote:On Tuesday, 19 January 2021 at 16:14:17 UTC, drug wrote:Sure. You don't even need to use isFinite like I wrote above because special values like inf and nan become some long values and will never equal to itself. Your question motivated me to do a little workout for my brains. Sorry if it confused you.Doesn't this pattern already cover all possible cases of `value` needed? void f(double value) { auto lvalue = cast(long)value; if (lvalue == value) // `value` lacks fraction and in range [long.min .. long.max] { // use long lvalue return; } // use double value }https://dlang.org/phobos/std_bitmanip.html#FloatRep
Jan 20 2021
On Tuesday, 19 January 2021 at 11:42:17 UTC, Per Nordlöw wrote:I want to convert a double to a long if conversion is lossless (without fractional part, non-nan, non-inf, within long-range, etc).And then? I mean: What do you want to do with the long what could not be done with the double in the first place? BTW: Has anybody noticed that there already might have been a loss of precision even before the conversion to long, since the mantissa of the double only entails 53 bit? long q = 1L << 53; long r = q + 1; assert (q != r); double s = q, t = r; assert (s == q); assert (t == r); assert (s != t); // fail
Jan 19 2021
On Tuesday, 19 January 2021 at 21:04:51 UTC, kdevel wrote:And then? I mean: What do you want to do with the long what could not be done with the double in the first place?Motivated question. We want to propagate to our system locally that a double received from a network communication actually is an integer and should be stored and treated as such in an algebraic type.
Jan 19 2021