Математическая операция для отражения итератора цикла относительно середины числа итераций - PullRequest
0 голосов
/ 04 октября 2018

Представьте, что у нас есть цикл с индексной переменной n, считающий от 1 до 6. Когда я прошел через этот цикл, я хочу напечатать значения

1
2
3
3
2
1

Есть ли элегантная математическая операция (т.е. избеганиеif заявления), которые могут это реализовать?Я знаю, например, что если я напечатаю

1 + modulo(n-1,3) 

, то будет напечатано

1
2
3
1
2
3

, но я хочу, чтобы вторая половина была обратной.Цикл всегда будет иметь четное количество итераций, если это поможет.Я пишу на Фортране 90.

Ответы [ 4 ]

0 голосов
/ 05 октября 2018

Рассмотрим

min(n, 7-n)

Это выражение создает 1, 2, 3, 3, 2, 1, когда n переходит от 1 к 6.В более общем смысле, если N является (четной) верхней границей для переменной n, формула принимает вид:

min(n, N+1-n)

, который выдает

1, 2, ..., N/2, N/2, N/2 - 1, ..., 2, 1

при выполнении nмежду 1 и N.

В случае, если N нечетно, та же формула генерирует последовательность

1, 2, ..., (N+1)/2, (N-1)/2, ..., 2, 1.

Например:

1, 2, 3, 4, 3, 2, 1

для N=7.

0 голосов
/ 04 октября 2018

Как насчет следующего:

do i=1,n
   print *, int(abs(i-n/2.0-0.5)+0.5)
end do

Это напечатает ожидаемый результат для четного n и вводит НОЛЬ для нечетного n.

0 голосов
/ 04 октября 2018

Достаточно ли элегантно следующее?Я думаю, что это намного яснее, чем запутанная математика

ian-admin@agon ~/work/stack $ cat merge.f90
Program test
  Implicit None
  Integer :: n
  Integer :: i
  Write( *, * ) 'n?'
  Read ( *, * ) n
  Do i = 1, n
     Write( *, * ) Merge( i, n - ( i - 1 ), i <= n / 2 )
  End Do
End Program test
ian-admin@agon ~/work/stack $ gfortran -std=f2003 -Wall -Wextra merge.f90 
ian-admin@agon ~/work/stack $ ./a.out
 n?
6
           1
           2
           3
           3
           2
           1
ian-admin@agon ~/work/stack $ ./a.out
 n?
7
           1
           2
           3
           4
           3
           2
           1
ian-admin@agon ~/work/stack $ 
0 голосов
/ 04 октября 2018
n = 6 
for i in range(1,n+1):
   print(min(i, n + 1 - i))
      or (// is integer division equivalent to bitshift right) 
   print(n//2 - abs(n + 1 - 2 * i)//2)

>> 1 2 3 3 2 1

Для нечетной длины - первый подход работает как есть, второй способ требует изменения на (n+1)//2 (он не прерывает работу для четной длины)

Битовый трюк, чтобы найти минимум двух 32-битные целые числа:

min = b+((a-b)&((a-b)>>31))
...