Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Помогите решить задачу / 25 сообщений из 35, страница 1 из 2
23.12.2005, 00:46
    #33453327
Luck
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
В одномерном массиве, состоящем из n вещественных элементов, вычислить:
1) максимальный по модулю элемент массива;
2) сумму элементов массива, расположенных между первым и вторым положительными элементами.
Преобразовать массив таким образом, чтобы элементы, равные нулю, располагались после всех остальных.
...
Рейтинг: 0 / 0
23.12.2005, 09:31
    #33453542
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
#include <math.h>
#include <stdio.h>

double func( double arr[], unsigned n, double* max )
{
	double sum =  0 . 0 ;
	unsigned int i =  0 , flag =  0 , insPos =  0 ;
	
	while( i < n ) {
		double val = arr[i];
		if( val ==  0 . 0  ) {
			if( !insPos ) insPos = i+ 1 ;
		} else {
			if( val >  0 . 0  ) {
				if( flag <  2  ) { flag =  1 ; sum += val; }
			} else {
				if( flag ==  1  ) { flag =  2 ; }
				val = fabs( val );
			}
			if( *max < val ) *max = val;
			if( insPos ) {
				arr[ insPos++ -  1  ] = arr[ i ];
			}
		}
		i++;
	}
	if( insPos )
		for( --insPos; insPos < n; insPos++ ) arr[ insPos ] =  0 . 0 ;
	return sum;
}

int main()
{
	double arr[] = { - 3 . 0 , - 2 . 0 ,  5 ,  0 ,  0 ,  7 ,  6 ,  0 , - 4 . 0 ,  3 ,  4  };
	unsigned sz = sizeof(arr)/sizeof(double), i;
	double max =  0 . 0 ;
	
	double sum = func( arr, sz, &max );

	printf( "Sum = %f, |Max| = %f, array:\n", sum, max );
	for( i =  0 ; i < sz; i++ )
		printf( "[%d] = %f\n", i, arr[i] );
	return  0 ;
}
--
There Ain't No Such Thing As A Free Lunch
...
Рейтинг: 0 / 0
23.12.2005, 09:36
    #33453553
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Упс! Малость не так. Не совсем верно понял второе условие.
Сейчас второй вариант нарисуюю
--
There Ain't No Such Thing As A Free Lunch
...
Рейтинг: 0 / 0
23.12.2005, 09:45
    #33453578
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Luck2) сумму элементов массива, расположенных между первым и вторым положительными элементами.

Включая эти элементы или исключая их?
...
Рейтинг: 0 / 0
23.12.2005, 09:52
    #33453592
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
BlackStar Luck2) сумму элементов массива, расположенных между первым и вторым положительными элементами.

Включая эти элементы или исключая их?
Блин! А ноль считается положительным? :)
...
Рейтинг: 0 / 0
23.12.2005, 17:40
    #33455151
Luck
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Спасибо, но по проще нельзя?
Не считая эти элименты.
...
Рейтинг: 0 / 0
23.12.2005, 20:11
    #33455349
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Ну тогда вот так. Это вариант когда 0 не считается положительным значением.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
#include <math.h>
#include <stdio.h>

double func( double arr[], unsigned n, double* max )
{
	double sum =  0 . 0 ;
	unsigned int i =  0 , flag =  0 , insPos =  0 ;
	
	while( i < n ) {
		double val = arr[i];
		if( val ==  0 . 0  ) {
			if( !insPos ) insPos = i+ 1 ;
		} else {
			if( val >  0 . 0  )	flag++;
			else {
				if( flag ==  1  ) sum += val;
				val = fabs( val );
			}
			if( *max < val ) *max = val;
			if( insPos ) arr[ insPos++ -  1  ] = arr[ i ];
		}
		i++;
	}
	if( insPos )
		for( --insPos; insPos < n; insPos++ ) arr[ insPos ] =  0 . 0 ;
	return sum;
}

int main()
{
	double arr[] = {  8 , - 3 . 0 , - 2 . 0 ,  5 ,  0 ,  0 ,  7 ,  6 ,  0 , - 12 . 0 ,  3 ,  4  };
	unsigned sz = sizeof(arr)/sizeof(double), i;
	double max =  0 . 0 ;
	
	double sum = func( arr, sz, &max );

	printf( "Sum = %f, |Max| = %f, array:\n", sum, max );
	for( i =  0 ; i < sz; i++ )
		printf( "[%d] = %f\n", i, arr[i] );
	return  0 ;
}

Если же хочется и 0 считать положительным надо поправить кусочек вот так
Код: plaintext
1.
2.
3.
4.
		if( val ==  0 . 0  ) {
			flag++;
			if( !insPos ) insPos = i+ 1 ;
		} else {

Ну куда уж проще? Или еще прокоментировать что каждая строка делает?
--
There Ain't No Such Thing As A Free Lunch
...
Рейтинг: 0 / 0
23.12.2005, 22:42
    #33455478
spectre
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
BlackStarЕсли же хочется и 0 считать положительным надо поправить кусочек вот так
"0" не является положительным числом.

А вот как можно посчитать сумму между первыми двумя положительными числами.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
double sumbetween(double*a,int n)
{
   double sum =  0 ;
   int i =  0 ;
   while(a[i++]<= 0 );
   while(a[i]<= 0 )sum+=a[i++];
   return sum;
}
...
Рейтинг: 0 / 0
24.12.2005, 01:52
    #33455562
Luck
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
нет, каждую строку коментировать не стоит.
Просто на сколько я понимаю здесь используется функция? а без неё никак?
прошу прощения если я не прав.Не давно только начал изучать
...
Рейтинг: 0 / 0
26.12.2005, 09:51
    #33456751
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Luckнет, каждую строку коментировать не стоит.
Просто на сколько я понимаю здесь используется функция? а без неё никак?
прошу прощения если я не прав.Не давно только начал изучать

Можно и без функции. Но зачем?
Функция func решает вашу задачу. Функция main (основная функция программы)
вызывает func с необходимыми данными и отображает результат.
func можно вызывать несколько раз, с разными исходными данными.
...
Рейтинг: 0 / 0
26.12.2005, 09:55
    #33456756
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
spectre BlackStarЕсли же хочется и 0 считать положительным надо поправить кусочек вот так
"0" не является положительным числом.

А вот как можно посчитать сумму между первыми двумя положительными числами.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
double sumbetween(double*a,int n)
{
   double sum =  0 ;
   int i =  0 ;
   while(a[i++]<= 0 );
   while(a[i]<= 0 )sum+=a[i++];
   return sum;
}


Угу. Тока мой вариант решает все три условия задачи за один проход
по массиву и не используя дополнительной памяти для упорядочивания
массива.
...
Рейтинг: 0 / 0
26.12.2005, 10:37
    #33456837
_Балтика
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Эххх... тоже чтоли молодость вспомнить, пока работы немного...
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
double func( double arr[], unsigned n, double* max )
{
    double sum =  0 , val;
    int flag =  0 , i =  0 ;
    while (i < n) {
        val = arr[i];
        if (*max < (val >=  0 )? val : -val)
            *max = val;
        if (flag ==  0 ) 
            flag =  1 ;
        else if (flag >  0 )
            if (val <=  0 ) 
                sum += val; 
            else 
                flag = - 1 ;
        if (val ==  0  && i < n -  1 )
        {
            ::memmove(arr[i], arr[i +  1 ], (--n - i) * sizeof(double)) 
            arr[n] =  0 ;
        }
        else
            i++;
     }
     return sum;
}
Не тестировал правда...
...
Рейтинг: 0 / 0
26.12.2005, 10:45
    #33456858
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
2 _Балтика:

двигать весь хвост массива на каждый ноль - не совсем экономично :)
если например размер массива 100000, и он хорошо разряжен нулевыми значениями...

--
There Ain't No Such Thing As A Free Lunch
...
Рейтинг: 0 / 0
26.12.2005, 10:52
    #33456877
_Балтика
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
_Балтика
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
double func( double arr[], unsigned n, double* max )
{
    double sum =  0 , val;
    int flag =  0 , i =  0 ;
    while (i < n) {
        val = arr[i];
        if (*max < (val >=  0 )? val : -val)
            *max = val;
        if (flag ==  0 ) 
            flag =  1 ;
        else if (flag >  0 )
            if (val <=  0 ) 
                sum += val; 
            else 
                flag = - 1 ;
        if (val ==  0  && i < n -  1 )
        {
            ::memmove(arr[i], arr[i +  1 ], (--n - i) * sizeof(double)) 
            arr[n] =  0 ;
        }
        else
            i++;
     }
     return sum;
}

Да, нужно бы еще учесть, что в массиве есть только одно положительное значение и в конце цикла while вставить что то типа
Код: plaintext
1.
2.
if (i >= n -  1  && flag >  0 )
    sum =  1 ;
Тогда возвращаемое положительное значение как раз и будет регистрировать этот факт.
...
Рейтинг: 0 / 0
26.12.2005, 10:52
    #33456879
Alex_VC
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Будьте осторожны, когда сравниваете вещественные числа, помните о двоичном представлении оных, ибо ошибки могуть крыться здесь...
...
Рейтинг: 0 / 0
26.12.2005, 10:56
    #33456895
_Балтика
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
BlackStar2 _Балтика:

двигать весь хвост массива на каждый ноль - не совсем экономично :)
если например размер массива 100000, и он хорошо разряжен нулевыми значениями...

--
There Ain't No Such Thing As A Free Lunch
А я и не двигаю
Код: plaintext
1.
::memmove(arr[i], arr[i +  1 ], (--n - i) * sizeof(double))
--n
...
Рейтинг: 0 / 0
26.12.2005, 11:00
    #33456907
_Балтика
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Извиняюсь, естественно вот так
Код: plaintext
1.
::memmove(&arr[i], &arr[i +  1 ], (--n - i) * sizeof(double));
...
Рейтинг: 0 / 0
26.12.2005, 11:06
    #33456923
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
_Балтика BlackStar2 _Балтика:

двигать весь хвост массива на каждый ноль - не совсем экономично :)
если например размер массива 100000, и он хорошо разряжен нулевыми значениями...

--
There Ain't No Such Thing As A Free Lunch
А я и не двигаю
Код: plaintext
1.
::memmove(arr[i], arr[i +  1 ], (--n - i) * sizeof(double))
--n

один черт. :)
и кстати передавать в memmove значения массива не самая удачная идея :)
наверное правильно вот так
Код: plaintext
1.
::memmove(&arr[i], &arr[i +  1 ], (--n - i) * sizeof(double))
...
Рейтинг: 0 / 0
26.12.2005, 11:11
    #33456937
_Балтика
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
BlackStar
один черт. :)
и кстати передавать в memmove значения массива не самая удачная идея :)

Это очепятка, я сам заметил :).
Почему же, один черт? В этом случае мы исключаем из движения все завершающие нули. Да и кол-во циклов уменьшается.
...
Рейтинг: 0 / 0
26.12.2005, 11:56
    #33457084
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
_Балтика BlackStar
один черт. :)
и кстати передавать в memmove значения массива не самая удачная идея :)

Это очепятка, я сам заметил :).
Почему же, один черт? В этом случае мы исключаем из движения все завершающие нули. Да и кол-во циклов уменьшается.
Потому что все равно приходится перемещать в памяти достаточно большие блоки информации. Теперь насчет циклов, вы думаете их нет в memmove?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
void * memmove(void *dst0, const void *src0, size_t length)
{
        char *dst = dst0;
        const char *src = src0;
        size_t t;

        if (length ==  0  || dst == src)          /* nothing to do */
                goto done;

        /*
         * Macros: loop-t-times; and loop-t-times, t>0
         */
#define TLOOP(s) if (t) TLOOP1(s)
#define TLOOP1(s) do { s; } while (--t)

        if ((unsigned long)dst < (unsigned long)src) {
                /*
                 * Copy forward.
                 */
                t = (uintptr_t)src;     /* only need low bits */
                if ((t | (uintptr_t)dst) & wmask) {
                        /*
                         * Try to align operands.  This cannot be done
                         * unless the low bits match.
                         */
                        if ((t ^ (uintptr_t)dst) & wmask || length < wsize)
                                t = length;
                        else
                                t = wsize - (t & wmask);
                        length -= t;
                        TLOOP1(*dst++ = *src++);
                }
                /*
                 * Copy whole words, then mop up any trailing bytes.
                 */
                t = length / wsize;
                TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
                t = length & wmask;
                TLOOP(*dst++ = *src++);
        } else {
                /*
                 * Copy backwards.  Otherwise essentially the same.
                 * Alignment works as before, except that it takes
                 * (t&wmask) bytes to align, not wsize-(t&wmask).
                 */
                src += length;
                dst += length;
                t = (uintptr_t)src;
                if ((t | (uintptr_t)dst) & wmask) {
                        if ((t ^ (uintptr_t)dst) & wmask || length <= wsize)
                                t = length;
                        else
                                t &= wmask;
                        length -= t;
                        TLOOP1(*--dst = *--src);
                }
                t = length / wsize;
                TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
                t = length & wmask;
                TLOOP(*--dst = *--src);
        }
done:
        return (dst0);
}
...
Рейтинг: 0 / 0
26.12.2005, 12:15
    #33457150
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Для предыдущего поста в перед функцией memmove надо добавить пару строчек
Код: plaintext
1.
2.
3.
4.
typedef int word;               /* "word" used for optimal copy speed */

#define wsize   sizeof(word)
#define wmask   (wsize -  1 )
--
There Ain't No Such Thing As A Free Lunch
...
Рейтинг: 0 / 0
26.12.2005, 12:22
    #33457178
_Балтика
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
BlackStar
Потому что все равно приходится перемещать в памяти достаточно большие блоки информации. Теперь насчет циклов, вы думаете их нет в memmove?

Вобщем то в этом случае memcpy можно использовать.
И надо еще посмотреть это ли используется в memmove?
Может быть из MEMCPY.ASM ? Там если посмотреть так делают:
................
rep movsd
................
А это, согласитесь, в несколько раз быстрее.
...
Рейтинг: 0 / 0
26.12.2005, 12:36
    #33457227
_Балтика
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
_Балтика BlackStar
Потому что все равно приходится перемещать в памяти достаточно большие блоки информации. Теперь насчет циклов, вы думаете их нет в memmove?

Вобщем то в этом случае memcpy можно использовать.
И надо еще посмотреть это ли используется в memmove?
Может быть из MEMCPY.ASM ? Там если посмотреть так делают:
................
rep movsd
................
А это, согласитесь, в несколько раз быстрее.
Именно из MEMCPY.ASM . (легко увидеть в дизасемблере).
...
Рейтинг: 0 / 0
26.12.2005, 13:25
    #33457353
BlackStar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
Ну уж если начали пиписками меряться... ;-))
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
double bigarr[ 100000 ];

int main()
{
	int n =  0 ;
	double arr[] = {  8 ,  0 , - 2 . 0 ,  5 ,  0 ,  0 ,  7 ,  6 ,  0 , - 12 . 0  };
	for( n =  0 ; n <  10000 ; n++ ) memcpy( &bigarr[n], arr,  10 *sizeof(double) );
	unsigned sz = sizeof(bigarr)/sizeof(double), i;
	double max =  0 . 0 , sum;

	time_t b = time(NULL);
	sum = func( bigarr, sz, &max );
	printf( "func(): %f\n", difftime( time(NULL), b ) );

	for( n =  0 ; n <  10000 ; n++ ) memcpy( &bigarr[n], arr,  10 *sizeof(double) );

	b = time(NULL);
	sum = func1( bigarr, sz, &max );
	printf( "func1(): %f\n", difftime( time(NULL), b ) );
	
	return  0 ;
}
Код: plaintext
1.
2.
3.
4.
bs@Hearse:~/prj> gcc -O3 -o test1 test.c 
bs@Hearse:~/prj> ./test1
func(): 0.000000
func1(): 33.000000

При этом я заменил в вашей функции (func1) memmove на memcpy,
а gcc при оптимизации -O3 как раз заменяет ее вызов на ассемблерный
код с участием rep movsl

PS Однако при малых размерах массива, разница будет не так заметна.
--
There Ain't No Such Thing As A Free Lunch
Код: plaintext
...
Рейтинг: 0 / 0
26.12.2005, 14:08
    #33457481
_Балтика
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите решить задачу
BlackStar
Код: plaintext
1.
2.
3.
4.
bs@Hearse:~/prj> gcc -O3 -o test1 test.c 
bs@Hearse:~/prj> ./test1
func(): 0.000000
func1(): 33.000000

Ну, это по-моему фантастика (33 сек!!!). Если только на
Код: plaintext
1.
sum = func1( bigarr, sz, &max );
брейкпойнта не было :) Во всяком случае при выполнении вот этого (массив в 10 раз больше)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
#include "stdafx.h"
#include <conio.h>
#include <time.h>

#define SZ_ARRAY	 1000000 

int _tmain(int argc, _TCHAR* argv[])
{

	double a[SZ_ARRAY];
	double	b[SZ_ARRAY];

	time_t t = time(NULL);
	memcpy(&a, &b, SZ_ARRAY * sizeof(double));
	printf( "memcpy time: %f\n", difftime( time(NULL), t ));

	t = time(NULL);
	for (int i =  0 ; i < SZ_ARRAY; i++)
		a[i] = b[i];
	printf( "for copy time(): %f\n", difftime( time(NULL), t ));
	getch();
	return  0 ;
}
получается
Код: plaintext
1.
2.
memcpy time: 0.000000
for copy time: 0.000000
Да, кстати, страннно, у меня и при /Od ассемблерный код подставляется.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Помогите решить задачу / 25 сообщений из 35, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]