g++ vs VS2013 C++ format/precyzja liczb

0

Cześć

Co muszę dodać do tego kodu żeby wyniki zapisywane do pliku pod Win7 (VS 2013) były zgodne(chyba) z oczekiwanymi - chodzi mi o precyzje/format ponieważ pod linuksem otrzymuje dobry(tez chyba) zapis liczb dla:

#include <string>
#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;

int main(void) {

	long double *fib = NULL;
	int n, i;
	string filename;

	cout << "Ile ?: ";
	cin >> n;

	if (n <= 0) {
		cout << " n <= 0" << endl;
		return 0;
	}

	fib = new long double[n];

	if (fib == NULL) {
		cout << "Mem alloc failure" << endl;
		return 1;
	}
#ifdef _WIN32
	fstream file("D:\\fib.txt", ios::trunc | ios::out);
#elif  __linux
	fstream file("/home/dawid/fib.txt", ios::trunc | ios::out);
#endif
	file.precision(10000);

	fib[0] = 1;
	fib[1] = 2;

	file << "Mem: " << n * sizeof(long double) << endl;
	file << "1 : " << fib[0] << endl;


	for (i = 2; i < n; i++) {
		fib[i] = fib[i - 1] + fib[i - 2];
		file << i  << " : " << fib[i] << endl;
	}

	delete fib;
	file.close();

	return 0;
} 

Wynik pod Windowsem:
79 : 37889062373143904
80 : 61305790721611584
81 : 99194853094755488
82 : 160500643816367070
83 : 259695496911122560
84 : 420196140727489660
85 : 679891637638612220
86 : 1100087778366101900
87 : 1779979416004714000
88 : 2880067194370816000
89 : 4660046610375530500
90 : 7540113804746346500
91 : 12200160415121877000
[...]
170 : 394810887814999250000000000000000000
171 : 638817435613190510000000000000000000
172 : 1.03362832342818980000[......]0000000000e+036

Wynik pod Ubuntu:

79 : 23416728348467685
80 : 37889062373143906
81 : 61305790721611591
82 : 99194853094755497
83 : 160500643816367088
84 : 259695496911122585
85 : 420196140727489673
86 : 679891637638612258
87 : 1100087778366101931
88 : 1779979416004714189
89 : 2880067194370816120
90 : 4660046610375530309
91 : 7540113804746346429
[...]
170 : 244006547798191185555677396319862784
171 : 394810887814999156252404086684516352
172 : 638817435613190341826095881513861120

Dzięki
Dawid

0

ps zrobilem okropnego byka - ma być delete [] fib ;) co do wyników to nie chodzi mi nawet o to żeby dobrze liczył kolejne liczby fibo tylko o sam zapis na stdout. przepraszam za post pod postem.

0

pod Visual Studio long double == double (sprawdź sizeofem)

0

Nie rozumiem jak to ma się ma do formatu wyjściowego ? Chodzi o to skąd win bierze te zera:
np:
dla liczby fibo(100) wynikiem jest: 354 224 848 179 261 915 075 - tak mi też wyświetla/zapisuje pod ubuntu
windows dla fibo(100) zapisuje ja do pliku tak: 354 224 848 179 262 000 000 - tak jakby zaokrąglał tego double'a

jeśli nie wywołam precision(X) to windows zapisze mi je jako ios::scientific
jeśli nie wywołam precision(x) i usatwie setf(ios::fixed) dostaje:
99 : 218922995834555200000.000000
100 : 354224848179262000000.000000
101 : 573147844013817200000.000000
czyli też w jakiś sposób zaokrąglone.

Jak tak potężną(długą; w sensie zajętych pikseli na ekranie ;-) ) liczbę wyświetlić/zapisać w C++ ?

0

Sprawdziłem jeszcze w C i jest dokładnie taka sama sytuacja - FreeBSD/Linux (wszedzie gcc) pokazuje liczby prawidłowo natomiast windows to zaokrągla czy tez formatuje:

 #include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {

	double *fib = NULL;
	int n, i;
	n = 500;

	fib = (double *)malloc(n * sizeof(double));

	if (fib == NULL) {
		printf("%s\n", "Mem alloc failure");
		return EXIT_FAILURE;
	}
	fib[0] = 1;
	fib[1] = 2;

#ifdef _WIN32
	FILE *fh = fopen("D:\\fib.txt", "w");
#elif __unix
	FILE *fh = fopen("./fib.txt", "w");
#endif

	fprintf(fh, "1 : %f\n", fib[0]);

	for (i = 2; i < n; i++) {
		fib[i] = fib[i - 1] + fib[i - 2];
		fprintf(fh, "%d : %f\n", i, fib[i]);
	}

	free(fib);
	fib = NULL;
	return EXIT_SUCCESS;
}
0

Okej pod Windowsem tak to wyczarowałem:

 

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

typedef __int64 Int64;
typedef unsigned __int64 UInt64;

int main(void) {

	UInt64 *fib = NULL;
	int n, i;
	n = 500;

	fib = (UInt64 *)malloc(n * sizeof(UInt64));

	if (fib == NULL) {
		printf("%s\n", "Mem alloc failure");
		return EXIT_FAILURE;
	}
	fib[0] = 1;
	fib[1] = 2;

#ifdef _WIN32
	FILE *fh = fopen("D:\\fib.txt", "w");
#elif __unix
	FILE *fh = fopen("./fib.txt", "w");
#endif

	fprintf(fh, "1 : %I64d\n", fib[0]);

	for (i = 2; i < n; i++) {
		fib[i] = fib[i - 1] + fib[i - 2];
		fprintf(fh, "%d : %I64d\n", i, fib[i]);
	}

	free(fib);
	fib = NULL;
	flcose(fh);
	fh = NULL;
	return EXIT_SUCCESS;
}

0

tak jakby zaokrąglał tego double'a
no to logiczne, skoro long double jest tym samym co double, to masz mniejszą precyzję niż long double pod GCC.

0

A tak poza tym skąd ta pewność, że dla g++ masz dobry wynik dla dużych liczb?
To, że nie kończy się zerami nie znaczy, że jest poprawnie.
Ja ci powiem, że z powodu precyzji long double masz zły wynik dla 170 http://www.wolframalpha.com/input/?i=fib%28171%29
Z tego co pamiętam, liczba znaczących cyfr dla long double to tylko 19 (tylko 4 więcej niż dla double).
http://ideone.com/eCeKVa
http://www.cplusplus.com/reference/cfloat/

1 użytkowników online, w tym zalogowanych: 0, gości: 1