Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 19, 2021 Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
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? |
January 19, 2021 Re: Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | 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
|
January 19, 2021 Re: Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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.
|
January 19, 2021 Re: Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | On 1/19/21 4:48 PM, Per Nordlöw wrote:
> 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.
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.
|
January 19, 2021 Re: Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
Posted in reply to drug | On 1/19/21 5:04 PM, drug wrote:
> On 1/19/21 4:48 PM, Per Nordlöw wrote:
>> 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.
>
> 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.
*fractional part
|
January 19, 2021 Re: Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
Posted in reply to drug | 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 |
January 19, 2021 Re: Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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
>
> Ali
>
That 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?
|
January 19, 2021 Re: Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
Posted in reply to drug | 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 |
January 19, 2021 Re: Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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.
|
January 19, 2021 Re: Convert double to long if lossless | ||||
---|---|---|---|---|
| ||||
Posted in reply to drug | On Tuesday, 19 January 2021 at 16:14:17 UTC, drug wrote:
>> https://dlang.org/phobos/std_bitmanip.html#FloatRep
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
}
|
Copyright © 1999-2021 by the D Language Foundation