Просто используйте term = Worksheets("Sheet1").Cells(1, 1).Value
Sheets
коллекция содержит также диаграммы и т. Д., Поэтому лучше использовать worksheets
IMO.
Кроме того, не используйте Select
, поскольку это плохая практика ( Избегайте использования SELECT или ACTIVATE )
Могло случиться так использованием DirectX или OpenGL в проекте? Раз так они могут выключить двойную точность, и Вы получите странные результаты.
Можно проверить настройки точности с
std::sqrt(x) * std::sqrt(x)
Результат должен быть достаточно близок к x. Я встретил эту проблему давным-давно, и проведите месяц, проверяя все формулы. Но затем я нашел
D3DCREATE_FPU_PRESERVE
Я попробовал плаванием вместо двойного, и я добираюсь 10.845110 в результате. Это все еще выглядит лучше, чем результат madalina.
Править:
Я думаю, что знаю, почему Вы добираетесь, это заканчивается. Если Вы получаете a, b, c и d параметры от где-то в другом месте, и Вы печатаете его, он дает Вам округленные значения. Затем при помещении его в Mathemtacia (или calc ;)) это даст Вам другой результат.
Я пытался изменить немного один из Ваших параметров. Когда я сделал:
double c = 2.7041304;
Я добираюсь 10.845806. Я только добавляю 0.0000004 к c! Таким образом, я думаю, что Ваши "ошибки" не являются ошибками. Распечатайте a, b, c и d с лучшей точностью и затем поместите их в Mathematica.
Проблема здесь состоит в том, что (c-a) является маленьким, таким образом, погрешности округления, свойственные от операций с плавающей точкой, увеличены в этом примере. Общее решение состоит в том, чтобы переделать Ваше уравнение так, чтобы Вы не делились на небольшое число, я не уверен, как Вы сделали бы это здесь все же.
Править:
Neil прав в своем комментарии к этому вопросу, я вычислил ответ в использовании VB, Удваивает и получил тот же ответ как mathematica.
Следующий код:
#include <iostream>
using namespace std;
double getSlope(double a, double b, double c, double d){
double slope;
slope=(d-b)/(c-a);
return slope;
}
int main( ) {
double s = getSlope(2.71156, -1.64161, 2.70413, -1.72219);
cout << s << endl;
}
дает результат 10,8452 с g ++. Как Вы распечатываете результат в своем коде?
Лучше Распечатайте аргументы, также. Когда Вы, как я предполагаю, передавая параметры в десятичной записи, Вы потеряете точность для каждого из них. Так как проблема - это, 1/5 является бесконечным рядом в двоичном файле, таким образом, например, 0.2 становится.001001001.... Кроме того, десятичные числа прерываются при преобразовании двоичного плавания в текстовое представление в десятичном числе.
Рядом с этим иногда компилятор предпочитает скорость точности. Это должно быть зарегистрированным переключателем компилятора.
Patrick, кажется, прав относительно (c-a) быть основной причиной:
d-b =-1,72219 - (-1,64161) =-0,08058
c-a = 2,70413 - 2,71156 =-0,00743
S = (d-b) / (c-a) =-0,08058/-0,00743 = 10,845222
Вы начинаете с шестью точностью цифр посредством вычитания, Вы получаете сокращение к 3 и четырем цифрам. Мое лучшее предположение - то, что Вы освобождаете дополнительную точность, потому что номер-0,00743 не может быть представлен exaclty в двойном. Попытайтесь использовать промежуточные переменные с большей точностью, как это:
double QSweep::getSlope(double a, double b, double c, double d)
{
double slope;
long double temp1, temp2;
temp1 = (d-b);
temp2 = (c-a);
slope = temp1/temp2;
return slope;
}
Результаты, которые Вы получаете, согласовываются с арифметикой на 32 бита. Не зная больше о Вашей среде, не возможно советовать, что сделать.
Принятие показанного кода - то, что работает, т.е. Вы ничего не преобразовываете в строки или плавания, затем в C++ нет фиксации. Это за пределами кода, который Вы показали, и зависит от среды.
Поскольку Patrick McDonald и Treb принесли и точность Ваших исходных данных и ошибку на a-c
, Я думал, что буду смотреть на это. Одна техника для рассмотрения погрешностей округления является арифметикой интервала, которая делает верхние и нижние границы, которые значение представляет явный (они неявны в числах с плавающей точкой и фиксируются с точностью до представления). Путем обработки каждого значения как верхней и нижней границы, и путем расширения границ ошибкой в представлении (приблизительно x * 2 ^-53 для двойного значения x), Вы получаете результат, который дает нижние и верхние границы на точности значения, принимая во внимание худшие ошибки точности случая.
Например, если Вы имеете значение в диапазоне [1.0, 2.0] и вычитаете из него значение в диапазоне [0.0, 1.0], затем результат должен находиться в диапазоне [ниже (0.0), выше (2.0)], как минимальный результат 1.0-1.0, и максимум 2.0-0.0. below
и above
эквивалентны полу и потолку, но для следующего представимого значения, а не для целых чисел.
Используя интервалы, которые представляют худший случай, дважды округляющийся:
getSlope(
a = [2.7115599999999995262:2.7115600000000004144],
b = [-1.6416099999999997916:-1.6416100000000002357],
c = [2.7041299999999997006:2.7041300000000005888],
d = [-1.7221899999999998876:-1.7221900000000003317])
(d-b) = [-0.080580000000000526206:-0.080579999999999665783]
(c-a) = [-0.0074300000000007129439:-0.0074299999999989383218]
to double precision [10.845222072677243474:10.845222072679954195]
Итак, хотя c-a
является маленьким по сравнению с c
или a
, это все еще большое сравненный с двойным округлением, поэтому при использовании худшего вообразимого округления двойной точности затем Вы могли бы положить что значение, чтобы быть точными 12 числам - 10.8452220727. Вы потеряли несколько чисел от двойной точности, но Вы все еще работаете к больше значению, чем своего входа.
Но если исходные данные были только с точностью до значащих цифр числа, то вместо того, чтобы быть двойным значением 2.71156 +/-eps, то входной диапазон будет [2.711555,2.711565], таким образом, Вы получите результат:
getSlope(
a = [2.711555:2.711565],
b = [-1.641615:-1.641605],
c = [2.704125:2.704135],
d = [-1.722195:-1.722185])
(d-b) = [-0.08059:-0.08057]
(c-a) = [-0.00744:-0.00742]
to specified accuracy [10.82930108:10.86118598]
который является намного более широким диапазоном.
Но необходимо было бы стараться изо всех сил отслеживать точность в вычислениях, и погрешности округления, свойственные от плавающей точки, не являются значительными в этом примере - это точно 12 числам с худшим округлением двойной точности случая.
С другой стороны, если Ваши исходные данные только известны 6 числам, на самом деле не имеет значения, добираетесь ли Вы 10.8557 или 10.8452. Оба в [10.82930108:10.86118598].
В то время как академическая дискуссия отлично подходит для изучения ограничений языков программирования, вы можете найти простейшее решение проблемы - структура данных для арифметики произвольной точности .
Это будет иметь некоторые накладные расходы, но вы сможете найти что-то с достаточно гарантированной точностью.