Skip to content

Instantly share code, notes, and snippets.

@ChenyangGao
Created January 21, 2023 08:30
Show Gist options
  • Save ChenyangGao/b0381a7eaf0e9b31115b8954fc81ffc2 to your computer and use it in GitHub Desktop.
Save ChenyangGao/b0381a7eaf0e9b31115b8954fc81ffc2 to your computer and use it in GitHub Desktop.
提供一些函数,做一些有关数字正负号相关的事情
#!/usr/bin/env python3
# coding: utf-8
"""这个模块提供了一些函数,做一些有关数字正负号相关的事情。
"""
__author__ = "ChenyangGao <https://chenyanggao.github.io/>"
__version__ = (0, 0, 1)
__all__ = [
"sign", "sign2", "turnsign", "bysign", "bysign1",
"bysign2", "mulsign",
]
from typing import TypeVar
R = TypeVar("R", int, float)
def sign(x: R, /) -> int:
"""返回数字的正负号。
- 如果 > 0,返回 1
- 如果 = 0,返回 0
- 如果 < 0,返回 -1
table::
x | sign(x)
---| ---
2 | 1
0 | 0
-2 | -1
doctest::
>>> sign(2)
1
>>> sign(0)
0
>>> sign(-2)
-1
"""
return -1 if x < 0 else x > 0
def sign2(x: R, /) -> int:
"""数字的正负号。
- 如果 < 0,返回 -1
- 否则返回 1(0 视为正数)
table::
x | sign2(x)
---|---
2 | 1
0 | 1
-2 | -1
doctest::
>>> sign2(2)
1
>>> sign2(0)
1
>>> sign2(-2)
-1
"""
return -1 if x < 0 else 1
def turnsign(x: R, p: bool, /) -> R:
"""如果 p 为 False,则改变 x 的正负号。
table::
x | p | turnsign(x, p)
---|---| ---
2 | T | 2
0 | T | 0
-2 | T | -2
2 | F | -2
0 | F | 0
-2 | F | 2
doctest::
>>> turnsign(2, True)
2
>>> turnsign(0, True)
0
>>> turnsign(-2, True)
-2
>>> turnsign(2, False)
-2
>>> turnsign(0, False)
0
>>> turnsign(-2, False)
2
"""
return x if p else -x
def bysign(x: R, p: bool, /) -> R:
"""如果 p 为 True,则返回 abs(x),否则返回 -abs(x)。
table::
x | p | bysign(x, p)
---|---|---
2 | T | 2
0 | T | 0
-2 | T | 2
2 | F |-2
0 | F | 0
-2 | F |-2
doctest::
>>> bysign(2, True)
2
>>> bysign(0, True)
0
>>> bysign(-2, True)
2
>>> bysign(2, False)
-2
>>> bysign(0, False)
0
>>> bysign(-2, False)
-2
"""
return x if (x < 0) ^ p else -x
def bysign1(x: R, y: R, /) -> R:
"""x 使用 y 的正负号,但如果 y 为 0,则 x 的符号不变。
函数的实现相当于
if y > 0:
return abs(x)
elif y < 0:
return -abs(x)
else:
return x
或者相当于
return x if y == 0 else sign(y) * abs(x)
NOTE: 当 y 不为 0 时,如果 x 和 y 的符号相同时,取 x,否则取 -x。
table::
x | y | bysign1(x, y)
---|---|---
2 | 2 | 2
0 | 2 | 0
-2 | 2 | 2
2 | 0 | 2
0 | 0 | 0
-2 | 0 |-2
2 |-2 |-2
0 |-2 | 0
-2 |-2 |-2
doctest::
>>> bysign1(2, 2)
2
>>> bysign1(0, 2)
0
>>> bysign1(-2, 2)
2
>>> bysign1(2, 0)
2
>>> bysign1(0, 0)
0
>>> bysign1(-2, 0)
-2
>>> bysign1(2, -2)
-2
>>> bysign1(0, -2)
0
>>> bysign1(-2, -2)
-2
"""
return x if y == 0 else bysign(x, y > 0)
def bysign2(x: R, y: R, /) -> R:
"""x 使用 y 的正负号,其中 0 视为正数。
函数的实现相当于
if y >= 0:
return abs(x)
else:
return -abs(x)
或者相当于
return sign2(y) * abs(x)
NOTE: 如果 x 和 y 的符号相同,取 x,否则取 -x
NOTE: 相当于 math.copysign(x, y)
table::
x | y | bysign2(x, y)
---|---|---
2 | 2 | 2
0 | 2 | 0
-2 | 2 | 2
2 | 0 | 2
0 | 0 | 0
-2 | 0 | 2
2 |-2 |-2
0 |-2 | 0
-2 |-2 |-2
doctest::
>>> bysign2(2, 2)
2
>>> bysign2(0, 2)
0
>>> bysign2(-2, 2)
2
>>> bysign2(2, 0)
2
>>> bysign2(0, 0)
0
>>> bysign2(-2, 0)
2
>>> bysign2(2, -2)
-2
>>> bysign2(0, -2)
0
>>> bysign2(-2, -2)
-2
"""
return bysign(x, y >= 0)
def mulsign(x: R, y: R, /) -> R:
"""x 的正负符号取 x 和 y 的符号相乘。
如果 y 为 0,则不影响 x 或者说视为正数(因为最终效果是等价的)。
函数的实现相当于
sn = sign(x) * sign(y)
return sn * abs(sign) if sn else x
或者相当于
sn = sign2(x) * sign2(y)
return sn * abs(sign)
table::
x | y | mulsign(x, y)
---|---|---
2 | 2 | 2
0 | 2 | 0
-2 | 2 |-2
2 | 0 | 2
0 | 0 | 0
-2 | 0 |-2
2 |-2 |-2
0 |-2 | 0
-2 |-2 | 2
doctest::
>>> mulsign(2, 2)
2
>>> mulsign(0, 2)
0
>>> mulsign(-2, 2)
-2
>>> mulsign(2, 0)
2
>>> mulsign(0, 0)
0
>>> mulsign(-2, 0)
-2
>>> mulsign(2, -2)
-2
>>> mulsign(0, -2)
0
>>> mulsign(-2, -2)
2
"""
return x if y >= 0 else -x
if __name__ == "__main__":
import doctest
doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment