Issue829370

Created on **2003-10-24 02:44** by **gekonntde**, last changed **2012-03-15 19:48** by **mark.dickinson**. This issue is now **closed**.

Messages (17) | |||
---|---|---|---|

msg54050 - (view) | Author: Konrad Voelkel (gekonntde) | Date: 2003-10-24 02:44 | |

python needs a signum function, def signum(self, int): if(int < 0): return -1; elif(int > 0): return 1; else: return int; |
|||

msg54051 - (view) | Author: Raymond Hettinger (rhettinger) * | Date: 2003-11-28 17:56 | |

Logged In: YES user_id=80475 With the use cases being infrequent and the pure python version being so easy, I think we ought to pass on this one. |
|||

msg54052 - (view) | Author: Raymond Hettinger (rhettinger) * | Date: 2004-01-01 06:35 | |

Logged In: YES user_id=80475 Closed due to lack of further interest or development. |
|||

msg155647 - (view) | Author: Frank Breitling (fkbreitl) | Date: 2012-03-13 19:24 | |

Its true. Python needs it as every scientific programming language needs it. Its a matter of completeness. This is a deficit. |
|||

msg155648 - (view) | Author: Merlijn van Deen (valhallasw) * | Date: 2012-03-13 19:31 | |

numpy.sign does this: http://docs.scipy.org/doc/numpy/reference/generated/numpy.sign.html |
|||

msg155652 - (view) | Author: Frank Breitling (fkbreitl) | Date: 2012-03-13 19:41 | |

That's too much for too little. The math module should cover the basics. |
|||

msg155653 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-03-13 19:44 | |

I disagree that this is useful enough to make it worth adding to the standard library. Between math.copysign and simple comparisons, I think all the common cases are well covered. And it's a simple one-line function: def signum(x): return (x > 0) - (x < 0) Frank, do you have any convincing use-cases that aren't already covered by math.copysign or simple two-way comparisons (e.g., x >= 0)? |
|||

msg155657 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-03-13 19:57 | |

See also the (fairly) recent python-ideas discussion starting here: http://mail.python.org/pipermail/python-ideas/2010-April/007136.html |
|||

msg155662 - (view) | Author: Frank Breitling (fkbreitl) | Date: 2012-03-13 20:43 | |

Mark, the convincing use-cases apear already on this page. People suggest the usage of numpy or the definition of all kinds of functions to accomplish this trivial task. But the users don't want to worry about this. They just want to use this function and not lose time figuring out how to best implement it in python. Copysign is not very intuitive e.g. because command completion on math.si_ fails and because it will not be a first result by search engines. The discussion is another example for the user request. And I have the feeling that with the time spend on it all different variations of signum functions could have been implemented including their documentation - although the implementation of your two line solution should have been satisfying for almost everybody... |
|||

msg155686 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-03-13 22:42 | |

> Mark, the convincing use-cases apear already on this page. I meant that I'd be interested to see examples of real code (e.g., specific numeric algorithms, etc.) where signum would be useful, and where existing functionality doesn't really do the job neatly. In most examples I can think of, I'm either creating a sign only to multiply some quantity by it later, or I'm making some decision based on the sign. In the first case, math.copysign usually fits the needs very well; in the second, I only need a two-way choice anyway (until Python gets three-way if statements). For example, a case that *seems* like it would be a good candidate for a sign function at first glance is computing the roots of a quadratic polynomial a*x**2 + b*x + c in a numerically safe manner. There what you want to do is find the auxiliary quantity q = -(b + sign(b)*sqrt(b**2 - 4*a*c)) and compute the roots as q / (2*a) and (2*c) / q. [The point of doing it this way is to avoid loss of significant digits from a subtraction of nearly-equal quantities in the case where b is large compared to a and c.] But that's a perfect use-case for copysign: instead of first computing the sign of b and then multiplying by the sqrt, you'd just compute q = -(b + copysign(sqrt(b**2 - 4*a*c), b)) Moreover, in this case you don't want the sign function described in this issue anyway, since it gives wrong results when b == 0; you want a two-valued sign function that always gives -1 or 1, even for an argument of 0. So, do you have better examples than the one above? |
|||

msg155733 - (view) | Author: Georg Brandl (georg.brandl) * | Date: 2012-03-14 07:22 | |

Can we add a comment to that effect to the math docs? |
|||

msg155737 - (view) | Author: Frank Breitling (fkbreitl) | Date: 2012-03-14 09:23 | |

Mark, https://en.wikipedia.org/wiki/Signum_function or elementary math books tell us that this function is called signum, sign or sgn. A library should adopt this standard for the same reason we don't want a ComputeTheSine or calcsin, which would be very confusing. As we learn from repeated discussions people want to use this signum function, no matter we can imagine this or not and no matter whether that functionality is hidden somewhere else. Since we are talking about not more than 5 lines of code, I don't see any reason not to have it. If there are some please let us know. |
|||

msg155885 - (view) | Author: Frank Breitling (fkbreitl) | Date: 2012-03-15 14:17 | |

Here an example where the signum function provides an elegant way to calculate the Julian date: def julian_date(YY,MM,DD,HR,Min,Sec,UTcor): return 367*YY - (7*(YY+((MM+9)/12))/4) + (275*MM/9)+ DD + 1721013.5 + UTcor/24 - 0.5*sign((100*YY)+MM-190002.5) + 0.5 + HR/24.0 + Min/(60.0*24.0) + Sec/(3600.0*24.0) http://aa.usno.navy.mil/faq/docs/JD_Formula.php http://www.krioma.net/blog/2011/09/python_julian_date.php By the way Julian date should be part of the time or datetime module. |
|||

msg155890 - (view) | Author: Merlijn van Deen (valhallasw) * | Date: 2012-03-15 14:31 | |

I'm not quite sure why that formula would be "elegant" in the first place, and I most certainly don't understand why 0.5*sign((100*YY)+MM-190002.5) + 0.5 is more elegant than ((100*YY)+MM > 190002.5) or (((YY = 1900) and (MM > 2.5)) or (YY > 1900)) or rather: implementing leap years correctly in the first place, so the formula also works outside of the 1800-2099 range. And, in general, I don't understand the problem. Everyone who does scientific computing has numpy *anyway*, so there is no gain for them. As a last note, the C math.h also doesn't have a sign() function, and only a copysign() function: http://en.wikipedia.org/wiki/C_mathematical_functions |
|||

msg155891 - (view) | Author: Merlijn van Deen (valhallasw) * | Date: 2012-03-15 15:01 | |

Although there is one use case which I now realise due to your post: easier 1-on-1 implementation of existing algorithms. Another possible reason to implement it is that it's not that hard to implement the sign() function wrongly, if it also has to work with nans. This implementation: def signum(x): return (x > 0) - (x < 0) returns 0 for nan, which is wrong (it should return nan). Another naive implementation def signum(x): return math.copysign(1, x) also fails for nan, and gives a result for +/- 0 that could be right or wrong, depending on context. |
|||

msg155896 - (view) | Author: Frank Breitling (fkbreitl) | Date: 2012-03-15 15:45 | |

Because its short. Because the former is a proper mathematical expression, while the latter is python jargon with limited use elsewhere. Exactly, why is there no correct implementation of Julian date in python time or datetime? For most practical purposes I can understand why most people would consider the above formula most useful and most elegant. Then what's the math module good for? So what? Is this the law of Moses? Or should we fall back to Assebmly? Python is supposed to be a high-level language not a stone age tool. However, I am glad you found at least another reason convincing to have this function. Cheers! |
|||

msg155897 - (view) | Author: Frank Breitling (fkbreitl) | Date: 2012-03-15 15:56 | |

Unfortunately my reply to the list lost all quotes, so I try to answer again through the web interface: --- > I'm not quite sure why that formula would be "elegant" in the first place, Because its short. > and I most certainly don't understand why 0.5*sign((100*YY)+MM-190002.5) + 0.5 is more elegant ... Because the former is a proper mathematical expression, while the latter is python jargon with limited use elsewhere. > or rather: implementing leap years correctly in the first place, so the formula also works outside of the 1800-2099 range. Exactly, why is there no correct implementation of Julian date in python time or datetime? For most practical purposes I can understand why most people would consider the above formula most useful and most elegant. > And, in general, I don't understand the problem. Everyone who does scientific computing has numpy *anyway*, so there is no gain for them. Then what's the math module good for? > As a last note, the C math.h also doesn't have a sign() function, and only a copysign() function: http://en.wikipedia.org/wiki/C_mathematical_functions So what? Is this the law of Moses? Or should we fall back to Assebmly? Python is supposed to be a high-level language not a stone age tool. However, I am glad you found at least another reason convincing to have this function. Cheers! |

History | |||
---|---|---|---|

Date | User | Action | Args |

2016-08-11 19:55:10 | r.david.murray | link | issue27739 superseder |

2012-03-15 19:48:33 | mark.dickinson | set | nosy:
- mark.dickinson |

2012-03-15 15:56:27 | fkbreitl | set | messages: + msg155897 |

2012-03-15 15:45:11 | fkbreitl | set | messages: + msg155896 |

2012-03-15 15:01:32 | valhallasw | set | messages: + msg155891 |

2012-03-15 14:31:28 | valhallasw | set | messages: + msg155890 |

2012-03-15 14:17:16 | fkbreitl | set | messages: + msg155885 |

2012-03-14 09:23:30 | fkbreitl | set | messages: + msg155737 |

2012-03-14 07:22:57 | georg.brandl | set | nosy:
+ georg.brandl messages: + msg155733 |

2012-03-13 22:42:00 | mark.dickinson | set | messages: + msg155686 |

2012-03-13 20:43:28 | fkbreitl | set | messages: + msg155662 |

2012-03-13 20:06:56 | mark.dickinson | set | versions: - Python 2.6, Python 3.1, Python 2.7, Python 3.2, Python 3.4 |

2012-03-13 19:57:06 | mark.dickinson | set | messages: + msg155657 |

2012-03-13 19:44:35 | mark.dickinson | set | nosy:
+ mark.dickinson messages: + msg155653 |

2012-03-13 19:41:40 | fkbreitl | set | messages: + msg155652 |

2012-03-13 19:31:39 | valhallasw | set | nosy:
+ valhallasw messages: + msg155648 |

2012-03-13 19:24:04 | fkbreitl | set | nosy:
+ fkbreitl messages: + msg155647 versions: + Python 2.6, Python 3.1, Python 2.7, Python 3.2, Python 3.3, Python 3.4 |

2003-10-24 02:44:04 | gekonntde | create |