Nan ind c как исправить

Давайте вспомним математику и выполним небольшое преобразование:

S^2=frac{sum{(x_i^2-2x_i overline{x}+overline{x}^2)}}{N}=frac{sum{x_i^2-(sum{x_i})^2/N}}{N}=frac{Nsum{x_i^2}-(sum{x_i})^2}{N^2}

Теперь нужно пройтись по массиву только один раз… Запишем код для double:

double Var(double* arr, size_t N)
{
    double x2 = 0, x = 0;
    for(size_t i = 0; i < N; ++i)
    {
        x2 += arr[i]*arr[i];
        x += arr[i];
    }
    return sqrt(N*x2-x*x)/N;
}

Теперь просто расширим его в шаблон для float и double с использованием концепта floating_point:

template<floating_point Double>
Double Var(Double* arr, size_t N)
{
    Double x2 = 0, x = 0;
    for(size_t i = 0; i < N; ++i)
    {
        x2 += arr[i]*arr[i];
        x += arr[i];
    }
    return sqrt(N*x2-x*x)/N;
}

Собственно, это всё…

Впрочем, можно еще один вариант, если передавать именно массив, то аргументом можно сделать ссылку на массив:

template<floating_point Double, size_t N>
Double Var(Double(&arr)[N])
{
    Double x2 = 0, x = 0;
    for(size_t i = 0; i < N; ++i)
    {
        x2 += arr[i]*arr[i];
        x += arr[i];
    }
    return sqrt(N*x2-x*x)/N;
}

и тогда при передаче массива не нужно передавать его размер…

P.S. Ах да, ваш код…

template <typename T>  // Ой. Сюда можно передать что угодно, например, int...
T Sigma_Array(const T* array, int count)
{
    T sum = 0;
    for (int i = 0; i < count; count++) // ЗАЧЕМ ВЫ УВЕЛИЧИВАЕТЕ COUNT?!!!
    {
        sum += array[i];
    }
    T average = sum / count;
    // Что вы делаете дальше?

    T square_s = 1. / count;  // Откуда это?

    for (int i = 0; i < count; count++) // ЗАЧЕМ ВЫ УВЕЛИЧИВАЕТЕ COUNT?!!!
    {
        T difference = array[i] - average;
        square_s *= pow(difference, 2); // Какое произведение?!
    }
    return sqrt(square_s);
}

Хотите в два прохода – так делайте это правильно:

template <typename T>
T Sigma_Array(const T* array, int count)
{
    T sum = 0;
    for (int i = 0; i < count; ++i) sum += array[i];
    T average = sum / count;
    T square_s = 0;
    for (int i = 0; i < count; ++i)
    {
        T difference = array[i] - average;
        square_s += difference*difference;
    }
    return sqrt(square_s/count);
}

MysteryMC

0 / 0 / 0

Регистрация: 09.02.2017

Сообщений: 26

1

26.11.2018, 23:10. Показов 3987. Ответов 4

Метки численные методы (Все метки)


Студворк — интернет-сервис помощи студентам

C++
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "stdafx.h"
#include<iostream>
using namespace std;
int main()
{
    setlocale(LC_ALL, "Russian");
    float A[10][10];
    float U[10][10];
    float b[10], x[10], y[10];
    int n, k;
    int i, j;
    float temp;
    cout << "Введите размерность матрицы " << endl;
    cin >> n;
label:
    cout << "Введите элементы матрицы " << n << "x" << n << endl;
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
        {
            cin >> A[i][j];
        }
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
        {
            U[i][j] = 0;
        }
    //проверка на симметричность
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
        {
            if (A[i][j] != A[j][i])
            {
                cout << "матрица не симетрична" << endl;
                goto label;
            }
        }
    cout << "введите елементы вектора b " << n << "x" << n << endl;
    for (i = 0; i < n; i++)
    {
        cin >> b[i];
    }
 
    for (int i = 0; i < n; i++)
    {
        temp = 0;
        for (int k = 0; k < i; k++)
            temp = temp + U[k][i] * U[k][i];
        U[i][i] = sqrt(A[i][i] - temp);
        for (j = i; j < n; j++)
        {
            temp = 0;
            for (k = 0; k < i; k++)
                temp = temp + U[k][i] * U[k][j];
            U[i][j] = (A[i][j] - temp) / U[i][i];
        }
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            cout << U[i][j] << " ";
        }
        cout << endl;
    }
    for (i = 0; i < n; i++)
    {
        temp = 0;
        for (int k = 0; k < i; k++)
            temp = temp + U[k][i] * y[k];
        y[i] = (b[i] - temp) / U[i][i];
    }
    for (i = n - 1; i >= 0; i--)
    {
        temp = 0;
        for (int k = i + 1; k < n; k++)
            temp = temp + U[i][k] * x[k];
        x[i] = (y[i] - temp) / U[i][i];
    }
    for (i = 0; i < n; i++)
        cout << "x" << i << "= " << x[i] << endl;
    system("pause");
}

[/CPP]
Исходные данные такие:
Матрица 123 214 341, вектор -3 -5 5.
На выходе получаю:
1 2 3
0 -nan – nan
0 0 -nan
x0=nan
x1=nan
x2=nan.
Я понимаю что nan означает что получилось не число, но не пойму что не так.



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

26.11.2018, 23:10

Ответы с готовыми решениями:

Ошибка -nan(ind) и nan
Доброго времени суток форумчане! Решаю задачу, в которой необходимо найти площадь треугольника по…

-nan(ind)
Что такое -nan(ind) и как это исправить?

#define _CRT_SECURE_NO_WARNINGS
#include &lt;iostream&gt;…

-nan(ind)
нужно вычислить значение функции, вроде сделал все проверки, но все равно при вводе отрицательного…

Ошибка -nan(ind)
Как исправить?

#include &lt;iostream&gt;
#include &lt;cmath&gt;
using namespace std;
int main() {
int…

4

74 / 58 / 31

Регистрация: 20.03.2017

Сообщений: 351

27.11.2018, 08:48

2

MysteryMC, ставь точки останова и смотри где это у тебя появляется.
Обычно NaN появляется, если было что-то из этого:

– все математические операции, содержащие NaN в качестве одного из операндов;
– деление нуля на ноль;
– деление бесконечности на бесконечность;
– умножение нуля на бесконечность;
– сложение бесконечности с бесконечностью противоположного знака;
– вычисление квадратного корня отрицательного числа;
– логарифмирование отрицательного числа.



0



0 / 0 / 0

Регистрация: 09.02.2017

Сообщений: 26

27.11.2018, 11:45

 [ТС]

3

Вот что у меня получилось, я поставил останову на вычисление квадратного корня. Но я не пойму почему у меня такие значения К и U[i][k]



0



0 / 0 / 0

Регистрация: 09.02.2017

Сообщений: 26

27.11.2018, 11:47

 [ТС]

4

Не загрузилось вложение

Миниатюры

-nan ind при решении сл
 



0



qwe123qwea

74 / 58 / 31

Регистрация: 20.03.2017

Сообщений: 351

27.11.2018, 12:32

5

MysteryMC, в строке 48

C++
1
U[i][i] = sqrt(A[i][i] - temp);

Получается что при второй итерации ты извлекаешь корень из отрицательного числа.



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

27.11.2018, 12:32

Помогаю со студенческими работами здесь

Выдаёт -nan(ind)
Header.h файл#pragma once
double f(double x);
double h(double a, double b, int n);
double hi(int…

Ошибка -nan (ind)
Не пойму, как избавится от этой ошибки
#include &quot;pch.h&quot;
#include &lt;iostream&gt;
#include &lt;fstream&gt;…

Ошибка nan(ind)
Помогите, пожалуйста. Что за ошибка nan(ind) в момент когда y должен быть равен 0

#include…

Ошибка -nan<ind>
#include &quot;pch.h&quot;
#include &lt;iostream&gt;
#include &lt;math.h&gt;
using namespace std;
int main()
{…

Почему выдает -nan(ind)
#include &lt;iostream&gt;
#include &lt;math.h&gt;

using namespace std;

int main() {

Что такое -nan<ind>
Написал код. После введения переменных получаю в консоли ответ &quot;-nan&lt;ind&gt;&quot;. В чём может быть…

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:

5



Знаток

(321),
закрыт



3 дня назад

Сергей Степанов

Просветленный

(45354)


1 год назад

У вас некоторые переменные из формулы не инициализированы. Например х и y. Если в y будет ноль, то выражение x/y вернет nan и эта ошибка передастся дальше по цепочке. То же касается тригонометрических функций.

Сергей СтепановПросветленный (45354)

1 год назад

ну хотябы ввести с клавиатуры перед основной формулой.
cin >> x >> y;
Компилятор обычно предупреждает, если есть неиспользованные или не инициализированные переменные чтобы не возникало ошибок.

Def

Просветленный

(25130)


1 год назад

Потому что переменная неинициализирована. Как исправить: 1). всегда инициализировать все переменные, которые можно инициализировать хотя бы дефолтными или нулевыми значениями. 2). Не пытаться использовать значения из неинициализированных переменных.

Сергей СтепановПросветленный (45354)

1 год назад

Вы похожи на врача, который даже не глядя на пациента ставит диагноз.
Новичек – почему в z – мусор?
Профессор – вы не инициализировали переменную.
Новичек – как же, вот z =…
Профессор да не эту, другую.
Можно же было просто сказать – x забыли инициализировать.
И добавить что переменные не инициализируются через запятую.

  • Forum
  • Beginners
  • -nan(ind)?

-nan(ind)?

So I’m writing a program that demonstrates Newton’s method to find a root of an equation. It outputs the estimated value of the root, the the true error and empirical error. After trying to run the program, the true error and estimated error were outputting “-nan(ind)”. I stepped through my program and found out that the original function for Newton’s method was returning this “-nan(ind)”. What is “-nan(ind)” and how do I avoid it in this program?

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
float newton(int count, float aval, float bval)
{
	count++; //Increase count to avoid going past contraint
	float cval = (aval + bval) / 2; //Get midpoint of interval
	float estroot = cval; //Set estimated root equal to midpoint
	cout << estroot << endl; //Output was root is estimated to be right now

	if (count == 20) //If constraint is reached, end recursion
	{
		return estroot;
	}

	else if (equation(aval) * equation(cval) < 0) //If root is in between left value and midpoint,
												  //recur with that interval
	{
		estroot = newton(count, aval, cval);
	}

	else if (equation(cval) * equation(bval) < 0) //If root is in between midpoint and right value,
												  //recur with that interval
	{
		estroot = newton(count, cval, bval);
	}
}

int main()
{
	char end;
	float aval = 1.0; //Initial a value 
	float bval = 4.0; //Initial b value
	float realroot = 2.0; //Real root
	float estroot;
	int count = 0; //count variable to make sure number of iterations does not exceed 20

	estroot = newton(count, aval, bval); //Function to find root
	float trueerr;
	trueerr = realroot - estroot;
	float emperr;
	emperr = equation(estroot) / derivative(estroot);
	cout << "True error = " << trueerr << "nEmpirical error = " << emperr << endl;

	cin >> end; //Pauses program so user can read output
}

NaN is “not a number”, possibly resulting from some mathematical faux pas like dividing by 0, or using something undefined. Difficult to tell without full code.

You appear to be implementing the bisection method, not the Newton(-Raphson) method for root-finding. I would expect to see the latter involving a function and its derivative, not your “empirical error”.

Can we see your equation( ) function, please: the function whose root you are trying to find.

Also note that your newton function won’t know what to return if equation(cval) is exactly equal to 0 – which, of course, is the root you are seeking.

Is there any reason you are using recursion rather than the more straightforward iteration?

Last edited on

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
float equation(float value)
{
	float output;

	output = 2 * (value * value) - 8; //Equation that we are trying to find root for, can be modified

	return output; //return output of equation
}

float derivative(float value)
{
	float output;

	output = 4 * value;

	return output;
}

Here’s the code for the equation and it’s first derivative. I’m using recursion even though it’s less straightforward because I honestly need more practice in recursion and this gave me a great excuse to try it.

I also tried implementing a condition for equation == 0, but the same problem is still happening

Your original routine newton( ) – your original post – does not return ANYTHING unless count = 20.

To remedy this, simply insert
return estroot;
at the end of this function (between lines 23 and 24 in your original post).

When I checked it, your program then worked.

There are multiple potential problems with your approach.
– Just change your original line 19 to plain
else
Then at least one option will be followed.

– Your method is BISECTION and not NEWTON-RAPHSON (aka Newton’s method).

– It would be far better done by iteration than recursion.

– You don’t check that your original aval and bval actually span the root.

– dividing by the derivative in line 39 will fail for many functions (e.g. y = (x-2)cubed), where the root also has zero slope.

Topic archived. No new replies allowed.

By using complex math it is possible … The problem is that the pow is using ln operation which is on complex domain multi-valued which means it has infinite number of valid result (as imaginary part of result is added with k*2*PI where k is any integer). So when the used result is not added with correct k then the result will be complex and not the one you want.

However for rooting (1.0/exponent -> integer) the k can be obtained directly as this:

int k=int(floor((1.0/exponent)+0.5))/2;

Which I discovered just now empirically. When I rewrite my complex math cpow to use this I got this C++ code:

//---------------------------------------------------------------------------
vec2 cadd(vec2 a,vec2 b)    // a+b
    {
    return a+b;
    }
vec2 csub(vec2 a,vec2 b)    // a-b
    {
    return a-b;
    }
vec2 cmul(vec2 a,vec2 b)    // a*b
    {
    return vec2((a.x*b.x)-(a.y*b.y),(a.x*b.y)+(a.y*b.x));
    }
vec2 cdiv(vec2 a,vec2 b)    // a/b
    {
    float an=atan2(-a.y,-a.x)-atan2(-b.y,-b.x);
    float  r=length(a)/length(b);
    return r*vec2(cos(an),sin(an));
    }
vec2 csqr(vec2 a)           // a^2
    {
    return cmul(a,a);
    }
vec2 cexp(vec2 a)           // e^a
    {
    //  e^(x+y*i)= e^x * e^(y*i) = e^x * ( cos(y) + i*sin(y) )
    return exp(a.x)*vec2(cos(a.y),sin(a.y));
    }
vec2 cln(vec2 a)            // ln(a) + i*pi2*k where k={ ...-1,0,+1,... }
    {
    return vec2(log(length(a)),atan2(a.y,a.x));
    }
vec2 cpow(vec2 a,vec2 b)    // a^b
    {
    return cexp(cmul(cln(a),b));
    }
vec2 ctet(vec2 a,int b)     // a^^b
    {
    vec2 c=vec2(1.0,0.0);
    for (;b>0;b--) c=cpow(a,c);
    return c;
    }
//-------------------------------------------------------------------------
vec2 cln(vec2 a,int k)          // ln(a) + i*pi2*k where k={ ...-1,0,+1,... }
    {
    return vec2(log(length(a)),atan2(a.y,a.x)+float(k+k)*M_PI);
    }
float mypow(float a,float b)        // a^b
    {
    if (b<0.0) return 1.0/mypow(a,-b);
    int k=0;
    if ((a<0.0)&&(b<1.0))       // rooting with negative base
        {
        k=floor((1.0/b)+0.5);
        k/=2;
        }
    return cexp(cmul(cln(vec2(a,0.0),k),vec2(b,0.0))).x;
    }
//-------------------------------------------------------------------------

I am using GLSL like math vec2 you can easily rewrite to x,y components instead for example to this:

//-------------------------------------------------------------------------
float mypow(float a,float b)        // a^b
    {
    if (b<0.0) return 1.0/mypow(a,-b);
    int k=0;
    if ((a<0.0)&&(b<1.0))           // rooting with negative base
        {
        k=floor((1.0/b)+0.5);
        k/=2;
        }
    float x,y;
    x=log(fabs(a));
    y=atan2(0.0,a)+(float(k+k)*M_PI);
    x*=b; y*=b;
//  if (fabs(exp(x)*sin(y))>1e-6) throw domain error;  // abs imaginary part is not zero
    return exp(x)*cos(y);                              // real part of result
    }
//-------------------------------------------------------------------------

Which returns real part of complex domain pow and also select the correct multi-valued cln sub-result. I also added domain test as a comment in the code in case you need/want to implement it.

Here result for your case:

mypow(-12.411202,0.200000) = -1.654866

Have tested more number and 1/odd number exponents and looks like it is working.

[Edit1] handling mixed exponents

Now if we have exponents in form a^(b0+1/b1) where b0,b1 are integers and a<0 we need to dissect the pow to 2 parts:

a^(b0+1/b1) = a^b0 * a^(1/b1)

so when added to above function:

//-------------------------------------------------------------------------
float mypow(float a,float b)            // a^b
    {
    if (b<0.0) return 1.0/mypow(a,-b);  // handle negative exponents
    int k;
    float x0,x,y,e,b0;
    k=0;                                // for normal cases k=0
    b0=floor(b);                        // integer part of exponent
    b-=b0;                              // decimal part of exponent
    // integer exponent (real domain power |a|^b0 )
    x0=pow(fabs(a),b0);
    if ((a<0.0)&&((int(b0)&1))==1) x0=-x0; // just add sign if odd exponent and negative base
    // decimal exponent (complex domain rooting a^b )
    if ((a<0.0)&&(b>0.0))               // rooting with negative base
        {
        k=floor((1.0/b)+0.5);
        k&=0xFFFFFFFE;
        }
    x=b*(log(fabs(a))); e=exp(x);
    y=b*(atan2(0.0,a)+(float(k)*M_PI));
    x=e*cos(y);
//  y=e*sin(y); if (fabs(y)>1e-6) throw domain error;
    return x*x0; // full complex result is x0*(x+i*y)
    }
//-------------------------------------------------------------------------

and sample output:

mypow(-12.41120243,3.200000) = 3163.76635742
mypow(3163.76635742,0.312500) = 12.41120243

Добавить комментарий