Created
January 21, 2023 08:30
-
-
Save ChenyangGao/b0381a7eaf0e9b31115b8954fc81ffc2 to your computer and use it in GitHub Desktop.
提供一些函数,做一些有关数字正负号相关的事情
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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