kubuntu — c ++ выдает ошибочные результаты вычислений. Можно ли это исправить?

Я задал следующий вопрос на форуме «Ask Ubuntu», и мне сказали, что этот вопрос не подходит для этого форума. Было предложено задать свой вопрос здесь. Я заранее прошу прощения, если это не подходящее место для этого вопроса.

В настоящее время я использую Java в качестве языка по умолчанию. Также в настоящее время я использую Kubuntu версии 12.04. Я конвертировал программу на c ++ в java, и результаты из программы java не совпадали с результатами из программы c ++. Я начал искать проблему, когда понял, что Java-программа дает правильные результаты, а программа C ++ не дает правильных результатов. Мой вопрос: может кто-нибудь объяснить, почему c ++ дает ошибочные результаты и можно ли это исправить?

Я написал две минимальные программы, чтобы проиллюстрировать проблему. Я также написал файл сценария для отображения двух программ, их компиляции и запуска. Результаты ниже. Очевидно, что значащие цифры находятся в одном и том же районе, однако при работе с большими степенями 10, такими как 30-я степень, разница значительна. Вот результаты моих тестовых программ и скриптов:

Linux Pegasus 3.2.0-54-generic # 82-Ubuntu SMP Вт 10 сентября 20:08:42 UTC 2013 x86_64 x86_64 x86_64 GNU / Linux

c ++ source

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
double testValue;
//---------------------------------------------------------------------
testValue = 1.0e0 * 1.9891e30;

cout << scientific << showpoint << right << setprecision(20)
<< "The test value = "<< setw(25) << testValue
<< "  the test value should be 1.9891e30\n"<< endl;

return 0;
}

Java-источник

class test
{
public static void main (String[] args)
{
double testValue;
//---------------------------------------------------------------------
testValue = 1.0e0 * 1.9891e30;

System.out.format
(
"The test value = %.20e  the test value should be 1.9891e30%n", testValue
);
}   // end main
}

тест g ++

Тестовое значение = 1.98909999999999988781e + 30 тестовое значение должно быть 1.9891e30

тест Java

Тестовое значение = 1.98910000000000000000e + 30 тестовое значение должно быть 1.9891e30

Очевидно, что значение testValue, созданное программой c ++, неверно, в то время как значение testValue, созданное программой java, является правильным. Любое понимание этой проблемы будет высоко оценено. Я искал в Google и здесь с помощью поисковых терминов «ошибочные вычисления C ++» без каких-либо существенных находок.

1

Решение

Я не уверен, как вы считаете, что это вычисление было ошибочным? Математика с плавающей точкой подвержена небольшим различиям в значениях. На одном компьютере с одним компилятором значения с плавающей запятой являются детерминированными, однако при использовании разных языков и разных компиляторов вы не гарантируете одинаковые результаты.

Мой старый профессор Брюс Доусон дает отличный обзор:
http://randomascii.wordpress.com/2012/04/05/floating-point-complexities/
http://randomascii.wordpress.com/2013/07/16/floating-point-determinism/

Результаты, которые вы видите выше, выглядят просто отлично для меня. Возможно, вам следует округлить до 3 цифр после десятичной точки и использовать это для сравнения полученных значений. С плавающей точкой вам будет трудно получить более точную информацию между различными языками и компиляторами.

Кроме того, я бы порекомендовал «неточность с плавающей точкой» в качестве лучшего поиска Google в следующий раз.

0

Другие решения

Код C ++ печатает фактическое значение, в то время как код Java округляет значение. Имейте в виду, что число 0.0001 как только 0.1 не может быть представлен точно в двоичном виде.

Вы можете получить его, чтобы напечатать фактическое значение с BigDecimal который будет таким же, как ваш вывод C ++:

import java.math.*;
class test
{
public static void main (String[] args)
{
double testValue;
testValue = 1.0e0 * 1.9891e30;

BigDecimal realvalue = new BigDecimal(testValue);
System.out.format
(
"The test value = %.20e the test value should be 1.9891e30%n", realvalue
);
}
}

Выход

Тестовое значение = 1.98909999999999988781e + 30 тестовое значение должно быть
1.9891e30

НАСКОЛЬКО МНЕ ИЗВЕСТНО, double в C ++ и Java оба будут содержать так же значение, но при печати их, вы видите разницу.

0

По вопросам рекламы [email protected]