digitalmars.D.learn - signbit question
- Miguel L (4/4) Mar 15 2018 Why does std.math.signbit only work for floating point types?
- Seb (38/42) Mar 15 2018 I guess because for integers you don't need to distinguish
- Adam D. Ruppe (11/12) Mar 15 2018 Integers are stored in an entirely different way, twos-complement
- Stefan Koch (7/12) Mar 15 2018 integers don't have a sign-bit.
- Miguel L (9/21) Mar 15 2018 Thanks. Just one more question:
- rumbu (11/34) Mar 15 2018 If you are comparing with an integer, please avoid signbit. It
- Miguel L (9/42) Mar 15 2018 There are various in my code there are more than two variables,
- Dlang User (24/74) Mar 15 2018 You could simplify that to this:
- ketmar (4/5) Mar 15 2018 than `f` will become zero very soon. something that "cannot happen" is t...
- Seb (2/14) Mar 15 2018 They generate the same assembly: https://godbolt.org/g/4ohTJx
- ashit axar (7/8) Mar 16 2018 import std.stdio;
Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advance
Mar 15 2018
On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types?I guess because for integers you don't need to distinguish between +0.0 and -0.0, so no one bother until now to add it to std.math. That being said there are a few options for integer types: --- import std.math, std.stdio; void main() { foreach (a; -1 .. 2) { "a:".writeln(a); signbit(cast(double) a).writefln!"signbit: %2d"; (cast(uint) a >> a.sizeof * 8 - 1).writefln!"bitshift: %2d"; (a < 0).writefln!"< 0:\t %2d"; writeln; } } --- https://run.dlang.io/is/pts6dj The first option is a bit slower for integers and the second and third option generate equivalent assembly [1], so I would recommend `a < 0` for integer types. [1] https://godbolt.org/g/4ohTJxwhat is the best way to compare the sign of a float with the sign of an integer?Ideas: 1) Make a PR to signbit to add integer support 2) Create your own signsbit a la: --- auto signbit(A)(A a) { static import std.math; import std.traits : isIntegral; static if (isIntegral!A) return a < 0; else return std.math.signbit(a); } ---
Mar 15 2018
On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:Why does std.math.signbit only work for floating point types?Integers are stored in an entirely different way, twos-complement instead of having a sign bit. You probably shouldn't be using the sign bit function at all, it is for digging deeper into the float binary format. Instead, I'd just say if(f > 0 && i > 0) if(f < 0 && i < 0) if(f == 0 && i == 0) etc. in math stuff to see if they have the same sign. floats have weird things like +0 and -0 which doesn't exist at all in ints...
Mar 15 2018
On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advanceintegers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Mar 15 2018
On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; .... if((a<0)==signbit(f)) {....} else {...}Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advanceintegers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Mar 15 2018
On Thursday, 15 March 2018 at 17:18:08 UTC, Miguel L wrote:On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:If you are comparing with an integer, please avoid signbit. It will return 1 also for -0.0, -inf and -nan. Don't bother also with signbit for integer types. The compiler usually outsmarts the programmer in finding the best way to compare an integer with 0. You can simply write: if (a < 0 && f < 0) {...} This will cover the [-inf..0) but not the NaN case. You can test it in a separate branch if (isNaN(f)) {...}On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; .... if((a<0)==signbit(f)) {....} else {...}Why does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advanceintegers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Mar 15 2018
On Thursday, 15 March 2018 at 17:31:38 UTC, rumbu wrote:On Thursday, 15 March 2018 at 17:18:08 UTC, Miguel L wrote:There are various in my code there are more than two variables, and i'd like to check when their signs differ.I am trying to avoid this, maybe there is no point in it: if(!((a>=0 && f>=0) || (a<0 && f<0))){ //signs are different .... } Thanks, anywayOn Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:If you are comparing with an integer, please avoid signbit. It will return 1 also for -0.0, -inf and -nan. Don't bother also with signbit for integer types. The compiler usually outsmarts the programmer in finding the best way to compare an integer with 0. You can simply write: if (a < 0 && f < 0) {...} This will cover the [-inf..0) but not the NaN case. You can test it in a separate branch if (isNaN(f)) {...}On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; .... if((a<0)==signbit(f)) {....} else {...}[...]integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Mar 15 2018
On 3/15/2018 12:39 PM, Miguel L wrote:On Thursday, 15 March 2018 at 17:31:38 UTC, rumbu wrote:You could simplify that to this: if ((a < 0) != (f < 0)) { } Or if you have more than two variables you could do something like this: bool AllSameSign(double[] args ...) { //Only need to check if there are more than one of them if (args.length > 1) { //Compare arg[0] to all the other args. for (int i = 1; i < args.length; i++) { if ((args[0] < 0) != (args[i] < 0)) { return false; } } } return true; } Which you could call like this, with as many variables as you like: AllSameSign(a,f);On Thursday, 15 March 2018 at 17:18:08 UTC, Miguel L wrote:There are various in my code there are more than two variables, and i'd like to check when their signs differ.I am trying to avoid this, maybe there is no point in it: if(!((a>=0 && f>=0) || (a<0 && f<0))){ //signs are different .... } Thanks, anywayOn Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:If you are comparing with an integer, please avoid signbit. It will return 1 also for -0.0, -inf and -nan. Don't bother also with signbit for integer types. The compiler usually outsmarts the programmer in finding the best way to compare an integer with 0. You can simply write: if (a < 0 && f < 0) {...} This will cover the [-inf..0) but not the NaN case. You can test it in a separate branch if (isNaN(f)) {...}On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; .... if((a<0)==signbit(f)) {....} else {...}[...]integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Mar 15 2018
Miguel L wrote:as the calculations on f guarantee it cannot be 0 at all.than `f` will become zero very soon. something that "cannot happen" is the most probable thing to happen. otherwise, LGTM.
Mar 15 2018
On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:They generate the same assembly: https://godbolt.org/g/4ohTJxWhy does std.math.signbit only work for floating point types? Is there an analogue function for integer types? what is the best way to compare the sign of a float with the sign of an integer? Thanks in advanceintegers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Mar 15 2018
On Thursday, 15 March 2018 at 17:30:48 UTC, Seb wrote:They generate the same assembly: https://godbolt.org/g/4ohTJximport std.stdio; void main() { writeln("hello"); } this generate error for dmd there.
Mar 16 2018
On Friday, 16 March 2018 at 07:00:36 UTC, ashit axar wrote:On Thursday, 15 March 2018 at 17:30:48 UTC, Seb wrote:`writeln` is not supported in betterC for dmd. Use `printf` instead.They generate the same assembly: https://godbolt.org/g/4ohTJximport std.stdio; void main() { writeln("hello"); } this generate error for dmd there.
Mar 16 2018
On Friday, 16 March 2018 at 08:35:58 UTC, Radu wrote:On Friday, 16 March 2018 at 07:00:36 UTC, ashit axar wrote:Or remove -betterC. I just used it because then no module constructors/destructors are generated and thus the assembly is even shorter.On Thursday, 15 March 2018 at 17:30:48 UTC, Seb wrote:`writeln` is not supported in betterC for dmd. Use `printf` instead.They generate the same assembly: https://godbolt.org/g/4ohTJximport std.stdio; void main() { writeln("hello"); } this generate error for dmd there.
Mar 16 2018