import random x=0 for i in range(7): for j in range(2): a=random.randint(-15,15) print(a, end=' ') if a<0 : x+=1 print() print("Отрицательных чисел:", x) 

I couldn’t think how to do something to read how many times the sequence of random numbers changed sign

  • Originally filled the curve code, fixed. - user234223
  • Sign change is already a derivative! In general, you just need to keep the previous value. - 0andriy
  • And with zero how to be? What is his sign? - m9_psy
  • What you want. This is a convention that you just need to designate. The idea is to read the next value and choose it ... Heh, here you have to think a little. In general, draw in the picture. His sign on the previous one is easy to calculate. If there was a minus, then plus and vice versa. - 0andriy
  • I suppose zero can be simply ignored in this case; D - user234223

3 answers 3

It is better to separate the code that generates random numbers from the code that counts the sign changes:

 def count_sign_reversals(numbers): it = iter(numbers) sign = next(it, 0) < 0 count = 0 for n in it: if sign is not (n < 0): count += 1 sign = not sign # sign changed return count 

Example:

 >>> import random >>> count_sign_reversals(random.randint(-15, 15) for _ in range(7*2)) 8 # one of possible answers >>> count_sign_reversals([1, -2, 3]) 2 >>> count_sign_reversals([1, -2]) 1 >>> count_sign_reversals([-1, 2]) 1 >>> count_sign_reversals([-1, -2]) 0 >>> count_sign_reversals([1, 2]) 0 >>> count_sign_reversals([1]) 0 >>> count_sign_reversals([]) 0 

If you want to distinguish between 0 and -0.0 , then you can filter through math.copysign() :

 from functools import partial numbers = map(partial(math.copysign, 1), numbers) 
  • Zero add a few - 0andriy
  • It does not affect. The sign in the code is signbit (determines whether the number is negative and how the name suggests it can take only two values). - jfs
  • so this is a limitation of architecture. In the ternary number system and the corresponding computers everything corresponds to mathematical representations. - 0andriy
  • where is the architecture. Do not need ternary computers to break the sequence in accordance with the function that returns three values. For example, the approach from the @MaxU response , quite working for integers: len(list(groupby(lst, key=lambda n: -1 if n < 0 else 1 if n else 0))) - (len(lst) > 0) (similar definition numpy.sign() uses). This does not mean that this “better” definition is just another and may be useful for some tasks. - jfs

The easiest and most reliable way is a naive solution with a counter and a cycle. But this is not our method. To start the text, then the code.

Take this array as an example: [-3, -4, 5, -5, 0, 3, -3] and leave only their sign instead of the numbers themselves: 1 for positive, -1 for negative: [-1, -1, 1, -1, 1, 1, -1] . Now we will take successively two adjacent numbers (their signs). This is what the sequence will look like:

 -3, -4 (-1, -1); -4, 5 (-1, 1); 5, -5 (1, -1); -5, 0 (-1, 1); 0, 3 (1, 1); 3, -3 (1, -1). 

Such pairs of numbers will be exactly len(list) - 1 , i.e. the length of the list is minus 1. Imagine that all numbers are positive. Then the sum of all pairs of characters (ie, units) will be equal to (len(list) - 1) * 2 . It is good if you do not just take a word, but check out this thesis. Each pair of numbers with different characters reduces the sum by 2. Denote the sum of these pairs of characters as summ and based on the above, the number of character shifts will be equal to ((len(list) - 1) * 2 - summ) / 2 . Let's write the sum as the sum of array elements with indices: summ: = | a 0 + a 1 | + | a 1 + a 2 | + | a 2 + a 3 | + | a 3 + a 4 | + | a 4 + a 5 | + | a 5 + a 6 |, where |...| - is the modulus of the number On this, in general, and all:

 import random # Все, что касается знаков спихиваем на библиотеку # Ибо можно попасть на всякие нехорошие вещи типа -0.0, nan, -nan и т.д. # Однако copysign вычисляет в процессе арктангенс(!!!) от числа и нельзя сказать, что # это очень быстро. Для ультра быстроты можно поиграть с битовыми сдвигами from math import copysign LIST_LEN = 7 target_list = [random.randint(-15, 15) for _ in range(LIST_LEN)] only_ones_list = [copysign(1, element) for element in target_list] summ = 0 for i in range(len(only_ones_list) - 1): summ += abs(only_ones_list[i] + only_ones_list[i + 1]) sign_change_count = ((len(only_ones_list) - 1) * 2 - summ) / 2 print(target_list) print(only_ones_list) print(sign_change_count) >>> [-6, 12, -3, -11, -12, -13, 7] >>> [-1, 1, -1, -1, -1, -1, 1] >>> 3.0 

The list of characters can not be compiled, of course, but immediately go through the original.

Now the most difficult thing is how this can be useful. First, there is no reasoning about zero-value or nan or anything else. We use the standard function and do not steam. Theoretically, you can do without conditional operators (inside abs and copysign) - you can try to calculate the sign and the module of the number using tricky bit operations. Theoretically, addition is also faster than multiplication, but the difference will be noticeable on large arrays.

  • if the sequence is empty [] , then the answer should be 0 (no sign changes), and not -1 as in your code. - jfs
  • 0 has no sign. - 0andriy
  • @ 0andriy, this is certainly true, but from the point of view of mathematics. However, there is a technical standard and when writing programs, the programmer must follow it. When it comes to zeros and stuff, the standard is called IEEE 754 , Signed zero . It can be considered a crutch (and in vain), but to ignore and close your eyes with the mantra "does not exist" is not worth it. - m9_psy
  • @ m9_psy, and you understand what it is all about? - 0andriy

If two numbers have different signs, their product is negative.

In this sense, 0 is processed correctly, it does not change the sign, regardless of whether the previous number is positive or negative, because the zero sign itself does not have. True, it is unclear whether the sign changes the sequence (-1, 0, +1) . On the one hand, no pair of neighboring elements has a different sign, on the other - there are both positive and negative elements.

 def count(l): prev = 0 r = 0 for value in l: r += 1 if prev * value < 0 else 0 prev = value if value != 0 else prev return r print count([-1, 0, 1, -1, 0, 0, 0, 2, 0, -1]) # -> 4 

So the sequence (-1.0, + 1) will give the result 1. If inside the loop instead of prev = value if value != 0 else prev write prev = value , it calculates the number of pairs of neighboring elements with different signs. (Neither a pair of 0, -1 nor a pair of 0, +1 have a different sign). In general, instead of prev * value < 0 you can write explicitly (prev > 0 and value < 0) or (prev < 0 and value > 0) will simply be more cumbersome. But it will be possible to consider 0 both positive and negative by changing the corresponding inequalities by> =.

  • one
    for float may break due to loss of precision or things like -0.0 . It is possible to filter through math.copysign() in such cases. - jfs
  • The value of the function sign of the number is not binary, but ternary! - 0andriy
  • @ 0andriy Who said that? 0 has no sign, neither +, nor -, nor any other. - andy.37
  • @jfs -0.0 - normally gives False when comparing and> 0 and <0. For two very small numbers, the product can actually be equal to 0. - andy.37
  • @ andy.37 is "normal" for different definitions different. The main thing to decide what definition is used. You are not required to follow the definition of math.copysign () - jfs