Fabio
Programador - Avançado
Programador - Avançado
Mensagens : 18259
Reputação : 388
Desde : 04/05/2012
Idade : 22
Link : gtamodvicio.blogspot.com
Ver perfil do usuáriohttp://gtamodvicio.blogspot.com
  • Reputação da mensagem: 100% (4 votos)
em Qui 19 Mar 2015, 02:32
AdvancedFloat é o nome de uma classe que criei para controlar números decimais (números não-inteiros, com virgula/ponto, ou sei lá do que você queira chamar) com alta precisão, cerca de 200 números após a virgula/ponto por padrão e pode ir até o infinito (Lembre-se que na computação nada é realmente infinito, mas com infinito, eu quero dizer que pode ter muitos números).

Boa parte dos operadores de comparação e cálculos estão implementados, com excessão do == e != (você pode fazer isso convertendo para double usando o .toDouble() e comparando-os), esses operadores serão implementados futuramente.

Funções estáticas:
AdvancedFloat AdvancedFloat::pow(number, expoent); // Potenciação
AdvancedFloat AdvancedFloat::sqrt(number); // Raiz quadrada

Em breve, raiz cúbida, quarta, etc.

Funções que eu acho necessário explicar:
uint64_t AdvancedFloat::getDivisionPrecision(); // retorna o número de casas após a virgula da precisão de divisão, detalhe: caso você dê set com um número com mais casas que isso, a função ajustará automaticamente.
uint64_t setDivisionPrecision(uint64_t n); // Relacionada a função acima, só que você envia um valor para dar set de precisão
const std::string get() const; // Pega o valor atual em forma de string, exemplo: 3.141592653589793, onde você poderá usar o std::stof(), std::stod(), std::stoi(), etc. para converter para tipos básicos.

OBS: A classe aceita somente PONTO, NÃO ACEITA VIRGULA.

Updates irão vir em um futuro próximo (ou nem tão próximo)

Como usar:
Código:
// PiTest.cpp : Defines the entry point for the console application.
//

#include "AdvancedFloat.h"
#include <cmath>
#include <iostream>

AdvancedFloat calcPi(AdvancedFloat precision){
 AdvancedFloat PI = 1.0, temp;

 AdvancedFloat p = 1.0;

 for (AdvancedFloat i = 0.0; i < precision; i++){
 temp = 1.0;
 temp /= (i * 2.0 + 3.0) * (p = p * 3.0);
 PI += (int(i.toInt()) % 2 == 0) ? -temp : temp;
 }
 return AdvancedFloat::sqrt(12.0) * PI;
}

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

 std::cout << calcPi(1000).get() << std::endl;

 return 0;
}
(Este exemplo foi originalmente postado aqui: http://brmodstudio.forumeiros.com/t3779-programinha-massa-pra-calcular-bhaskara-e-pitagoras)

Problemas:
EXTREMAMENTE LENTO para ser usada em aplicações que necessitem de velocidade;
Depende da biblioteca de terceiros chamada BigInt.

AdvancedFloat.h
Código:
#pragma once
#ifndef _ADVANCEDFLOAT_H_
#define _ADVANCEDFLOAT_H_

#include "BigInt.h"
#include <string>
#include <cmath>
#include <cstdio>
#include <cstdint>
#include <cstdlib>
#include <cstring>

class AdvancedFloat{
 BigInt number;
 unsigned int decs;
 uint64_t division_precision;

public:

 void set(std::string num);
 void set(double n);
 const std::string get() const;
 
 inline const uint64_t getDivisionPrecision() const
 {
 return division_precision;
 }

 inline const uint64_t setDivisionPrecision(uint64_t n)
 {
 return division_precision = n;
 }

 AdvancedFloat &operator/=(const AdvancedFloat &nToCalc);
 AdvancedFloat &operator*=(const AdvancedFloat &nToCalc);
 AdvancedFloat &operator+=(const AdvancedFloat &nToCalc);
 AdvancedFloat &operator-=(const AdvancedFloat &nToCalc);

 inline AdvancedFloat operator++(){ *this += 1.0; return *this; }
 inline AdvancedFloat operator--(){ *this -= 1.0; return *this; }

 static inline AdvancedFloat pow(const AdvancedFloat &n, const AdvancedFloat &e)
 {
 AdvancedFloat result = 1.0;
 for (AdvancedFloat i = 0.0; i < e; i++)
 result *= n;
 return result;
 }

 static AdvancedFloat sqrt(const AdvancedFloat &n);

 AdvancedFloat &operator=(const AdvancedFloat &nToCalc);

 bool operator<(const AdvancedFloat &nToCompare) const;
 bool operator>(const AdvancedFloat &nToCompare) const;
 bool operator<=(const AdvancedFloat &nToCompare) const;
 bool operator>=(const AdvancedFloat &nToCompare) const;

 AdvancedFloat operator/(const AdvancedFloat &nToCalc) const;
 AdvancedFloat operator*(const AdvancedFloat &nToCalc) const;
 AdvancedFloat operator+(const AdvancedFloat &nToCalc) const;
 AdvancedFloat operator-(const AdvancedFloat &nToCalc) const;

 inline AdvancedFloat operator-() const
 {
 return AdvancedFloat(*this * -1.0);
 };

 inline double toDouble() const
 {
 return std::stod(get());
 }

 inline int toInt() const
 {
 return std::stoi(get());
 }

 AdvancedFloat();
 AdvancedFloat(const char *num);
 AdvancedFloat(const std::string &num);
 AdvancedFloat(const BigInt &num);
 AdvancedFloat(double num);
};



#endif

AdvancedFloat.cpp
Código:
#include "AdvancedFloat.h"
#include <vector>

void AdvancedFloat::set(std::string num)
{
 size_t n = num.find_first_of('.');
 decs = 0;

 if (n != num.npos)
 {
 n++;
 decs = num.length() - n;
 }
 else
 {
 number = num;
 return;
 }

 auto str_replace = [](const std::string &search, const std::string &replace, std::string &subject)
 {
 std::string buffer;

 int sealeng = search.length();
 int strleng = subject.length();

 if (sealeng == 0)
 return subject;

 for (int i = 0, j = 0; i<strleng; j = 0)
 {
 while (i + j<strleng && j<sealeng && subject[i + j] == search[j])
 j++;
 if (j == sealeng)
 {
 buffer.append(replace);
 i += sealeng;
 }
 else
 {
 buffer.append(&subject[i++], 1);
 }
 }
 subject = buffer;
 return buffer;
 };

 str_replace(".", "", num);

 number = num;

 if (decs > division_precision)
 division_precision = decs + 16;
}

void AdvancedFloat::set(double n)
{
 /*std::string result;
 double integ = floor(n);
 double dec = n - integ;

 static const int precisionLimit = 0x20;

 uint64_t p1 = integ;
 result = std::to_string((int64_t)p1);

 double c = integ, d = n;
 std::string decimalPart;

 for (int i = 1; (d - c != 0) && i < precisionLimit; i++)
 {
 c = (d - c) * 10.0;
 d = c;
 c = floor(c);
 decimalPart += std::to_string((uint64_t)c);
 }

 if (decimalPart.length() > 0)
 {
 result += ".";
 result += decimalPart;
 }*/

 set(std::to_string(n));
}

bool AdvancedFloat::operator<(const AdvancedFloat &nToCompare) const
{
 std::string num1 = number.ToString();
 std::string num2 = nToCompare.number.ToString();
 int twoDoublePrecision = division_precision * 2.0;
 int nToCalcDecs = nToCompare.decs;

 if (decs < twoDoublePrecision)
 {
 num1.insert(num1.end(), twoDoublePrecision - decs, '0');
 }

 if (nToCalcDecs < twoDoublePrecision)
 {
 num2.insert(num2.end(), twoDoublePrecision - nToCalcDecs, '0');
 }

 return BigInt(num1) < BigInt(num2);
}

bool AdvancedFloat::operator>(const AdvancedFloat &nToCompare) const
{
 std::string num1 = number.ToString();
 std::string num2 = nToCompare.number.ToString();
 int twoDoublePrecision = division_precision * 2.0;
 int nToCalcDecs = nToCompare.decs;

 if (decs < twoDoublePrecision)
 {
 num1.insert(num1.end(), twoDoublePrecision - decs, '0');
 }

 if (nToCalcDecs < twoDoublePrecision)
 {
 num2.insert(num2.end(), twoDoublePrecision - nToCalcDecs, '0');
 }

 return BigInt(num1) > BigInt(num2);
}

bool AdvancedFloat::operator<=(const AdvancedFloat &nToCompare) const
{
 std::string num1 = number.ToString();
 std::string num2 = nToCompare.number.ToString();
 int twoDoublePrecision = division_precision * 2.0;
 int nToCalcDecs = nToCompare.decs;

 if (decs < twoDoublePrecision)
 {
 num1.insert(num1.end(), twoDoublePrecision - decs, '0');
 }

 if (nToCalcDecs < twoDoublePrecision)
 {
 num2.insert(num2.end(), twoDoublePrecision - nToCalcDecs, '0');
 }

 return BigInt(num1) <= BigInt(num2);
}

bool AdvancedFloat::operator>=(const AdvancedFloat &nToCompare) const
{
 std::string num1 = number.ToString();
 std::string num2 = nToCompare.number.ToString();
 int twoDoublePrecision = division_precision * 2.0;
 int nToCalcDecs = nToCompare.decs;

 if (decs < twoDoublePrecision)
 {
 num1.insert(num1.end(), twoDoublePrecision - decs, '0');
 }

 if (nToCalcDecs < twoDoublePrecision)
 {
 num2.insert(num2.end(), twoDoublePrecision - nToCalcDecs, '0');
 }

 return BigInt(num1) >= BigInt(num2);
}

AdvancedFloat &AdvancedFloat::operator=(const AdvancedFloat &nToCalc)
{
 decs = nToCalc.decs;
 number = nToCalc.number;
 return *this;
}

AdvancedFloat &AdvancedFloat::operator*=(const AdvancedFloat &nToCalc)
{
 number *= nToCalc.number;
 decs += nToCalc.decs;

 if (decs > division_precision)
 division_precision = decs + 16;

 return *this;
}

AdvancedFloat &AdvancedFloat::operator/=(const AdvancedFloat &nToCalc)
{
 if (decs > division_precision)
 division_precision = decs + 16;
 
 std::string num1 = number.ToString();
 std::string num2 = nToCalc.number.ToString();
 int twoDoublePrecision = division_precision * 2.0;
 int nToCalcDecs = nToCalc.decs;

 if (decs < twoDoublePrecision)
 {
 num1.insert(num1.end(), twoDoublePrecision - decs, '0');
 decs = twoDoublePrecision;
 }

 if (nToCalcDecs < division_precision)
 {
 num2.insert(num2.end(), division_precision - nToCalcDecs, '0');
 nToCalcDecs = division_precision;
 }

 number = num1;
 number /= BigInt(num2);

 num1 = number.ToString();

 decs -= division_precision;

 int i = number.Length() - 1, size = number.Length() - decs + 2;

 if (size > 0){
 for (; i > size; i--){
 if (num1[i] != '0')
 break;
 }
 num1.resize(i);

 decs -= number.Length() - i;
 }

 number = num1;

 return *this;
}

AdvancedFloat &AdvancedFloat::operator+=(const AdvancedFloat &nToCalc)
{
 std::string num1 = number.ToString();
 std::string num2 = nToCalc.number.ToString();

 if (decs > nToCalc.decs)
 {
 num2.insert(num2.end(), decs - nToCalc.decs, '0');
 }
 else
 {
 num1.insert(num1.end(), nToCalc.decs - decs, '0');
 number = num1;
 }

 number += BigInt(num2);

 if (nToCalc.decs > decs)
 decs = nToCalc.decs;

 if (decs > division_precision)
 division_precision = decs + 16;

 return *this;
}

AdvancedFloat &AdvancedFloat::operator-=(const AdvancedFloat &nToCalc)
{
 std::string num1 = number.ToString();
 std::string num2 = nToCalc.number.ToString();

 if (decs > nToCalc.decs)
 {
 num2.insert(num2.end(), decs - nToCalc.decs, '0');
 }
 else
 {
 num1.insert(num1.end(), nToCalc.decs - decs, '0');
 number = num1;
 }


 number -= BigInt(num2);

 if (nToCalc.decs > decs)
 decs = nToCalc.decs;

 if (decs > division_precision)
 division_precision = decs + 16;

 return *this;
}

const std::string AdvancedFloat::get() const
{
 std::string result = number.ToString();

 if (number.IsPositive())
 {
 int leng = result.length();
 leng -= decs;

 if (leng <= 0)
 {
 leng *= -1;
 ++leng;
 result = std::string(leng, '0') + result;
 }
 }
 else
 {
 int leng = result.length();
 leng -= decs;

 if (leng <= 1)
 {
 leng *= -1;
 leng += 2;

 result.insert(1 + result.find_first_of('-'), leng, '0');
 }
 }

 if (decs)
 result.insert(result.length() - decs, 1, '.');

 return result;
}

AdvancedFloat AdvancedFloat::operator / (const AdvancedFloat &nToCalc) const
{
 return AdvancedFloat(*this) /= nToCalc;
}

AdvancedFloat AdvancedFloat::operator*(const AdvancedFloat &nToCalc) const
{
 return AdvancedFloat(*this) *= nToCalc;
}

AdvancedFloat AdvancedFloat::operator+(const AdvancedFloat &nToCalc) const
{
 return AdvancedFloat(*this) += nToCalc;
}

AdvancedFloat AdvancedFloat::operator-(const AdvancedFloat &nToCalc) const
{
 return AdvancedFloat(*this) -= nToCalc;
}

AdvancedFloat AdvancedFloat::sqrt(const AdvancedFloat &n)
{
 auto minDiv = [](const AdvancedFloat &n)
 {
 int result = 2;
 for (result = 2; result < n.toInt() && n.toInt() % result != 0; result++);
 return result;
 };

 auto root = [](double x)
 {
 const AdvancedFloat startRoot = floor(std::sqrt(x)) + 1.0;
 const AdvancedFloat X = x;
 const static AdvancedFloat two = 2.0;
 AdvancedFloat result = startRoot;

 for (int i = 0, size = startRoot.getDivisionPrecision() / 2.0; i < size; i++){
 result = (result + X / result) / two;
 }
 return result;
 };

 AdvancedFloat calc = n;
 std::vector < int64_t > divs;

 for (double mDiv = 1; calc.toInt() != 1; divs.push_back(mDiv = minDiv(calc)), calc /= mDiv);

 AdvancedFloat result = 1.0;

 for (int i = 0, size = divs.size() / 2.0; i < size; i++){
 result *= (double)divs[i * 2];
 }

 if (divs.size() % 2 != 0)
 result *= root(divs[divs.size() - 1]);

 return result;
}

AdvancedFloat::AdvancedFloat()
{
 decs = 0;
 number = "0";

 division_precision = 200;
}

AdvancedFloat::AdvancedFloat(const std::string &num)
{
 decs = 0;
 number = "0";
 division_precision = 200;

 set(num);
}

AdvancedFloat::AdvancedFloat(const BigInt &num)
{
 decs = 0;
 number = num;
 division_precision = 200;
}

AdvancedFloat::AdvancedFloat(const char *num)
{
 decs = 0;
 number = "0";
 division_precision = 200;

 set(num);
}

AdvancedFloat::AdvancedFloat(double num)
{
 decs = 0;
 number = "0";
 division_precision = 200;

 set(num);
}


Última edição por Fabio em Qui 19 Mar 2015, 02:53, editado 7 vez(es)

______________________________
AdvancedFloat 0.1b 226c0ef57f9d7520d171cbadc68b3c56
Modifico quase qualquer coisa.   :)
------------------>>>http://gtamodvicio.blogspot.com/<<<------------------
AdvancedFloat 0.1b 76561198069372249
Meu PC:
Spoiler:

Configurações PC:
*Processador: Intel Core i7 4790K 4.00GHz LGA1150
*Placa Mãe: GIGABYTE GA-H97M-D3H Intel (LGA1150)
*HD: 1TB Seagate Barracuda 64MB Sata III 7200RPM (2x - RAID 0)
*HD²: SAMSUNG M3 Externo USB 5400RPM 1TB
*Placa de vídeo: Nvidia GTX660 2GB DDR5 192bit EVGA
*RAM: 8GB DDR3 1600MHZ Kingston HYPER X BEAST (2x4GB)
*Fonte: Corsair 600W Reais CX600M Modular - CP-9020060-WW (80 Plus Bronze)
*Gabinete: Gabinete Raidmax Super Hurricane Branco - 248WB
*Monitor: LG 23MP55HQ Full HD HDMI 23'
Junior_Djjr
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22701
Reputação : 727
Desde : 03/05/2012
Idade : 23
Localização : Ibitinga - SP
Link : www.MixMods.com.br
Ver perfil do usuáriohttp://MixMods.com.br
em Qui 19 Mar 2015, 02:39
eita

será alguem jah criou alguma coisa desse tipo? bem loco

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
Fabio
Programador - Avançado
Programador - Avançado
Mensagens : 18259
Reputação : 388
Desde : 04/05/2012
Idade : 22
Link : gtamodvicio.blogspot.com
Ver perfil do usuáriohttp://gtamodvicio.blogspot.com
em Qui 19 Mar 2015, 02:44
@Junior_Djjr escreveu:eita

será alguem jah criou alguma coisa desse tipo? bem loco

Provavelmente sim, mas é difícil encontrar pokerface

______________________________
AdvancedFloat 0.1b 226c0ef57f9d7520d171cbadc68b3c56
Modifico quase qualquer coisa.   :)
------------------>>>http://gtamodvicio.blogspot.com/<<<------------------
AdvancedFloat 0.1b 76561198069372249
Meu PC:
Spoiler:

Configurações PC:
*Processador: Intel Core i7 4790K 4.00GHz LGA1150
*Placa Mãe: GIGABYTE GA-H97M-D3H Intel (LGA1150)
*HD: 1TB Seagate Barracuda 64MB Sata III 7200RPM (2x - RAID 0)
*HD²: SAMSUNG M3 Externo USB 5400RPM 1TB
*Placa de vídeo: Nvidia GTX660 2GB DDR5 192bit EVGA
*RAM: 8GB DDR3 1600MHZ Kingston HYPER X BEAST (2x4GB)
*Fonte: Corsair 600W Reais CX600M Modular - CP-9020060-WW (80 Plus Bronze)
*Gabinete: Gabinete Raidmax Super Hurricane Branco - 248WB
*Monitor: LG 23MP55HQ Full HD HDMI 23'
Thelost
Programador - Avançado
Programador - Avançado
Mensagens : 10179
Reputação : 265
Desde : 08/11/2012
Ver perfil do usuário
em Qui 19 Mar 2015, 11:14
+
Fabio
Programador - Avançado
Programador - Avançado
Mensagens : 18259
Reputação : 388
Desde : 04/05/2012
Idade : 22
Link : gtamodvicio.blogspot.com
Ver perfil do usuáriohttp://gtamodvicio.blogspot.com
em Sex 20 Mar 2015, 02:32
@Thelost escreveu:+

Vlw




O tópico já era okay

______________________________
AdvancedFloat 0.1b 226c0ef57f9d7520d171cbadc68b3c56
Modifico quase qualquer coisa.   :)
------------------>>>http://gtamodvicio.blogspot.com/<<<------------------
AdvancedFloat 0.1b 76561198069372249
Meu PC:
Spoiler:

Configurações PC:
*Processador: Intel Core i7 4790K 4.00GHz LGA1150
*Placa Mãe: GIGABYTE GA-H97M-D3H Intel (LGA1150)
*HD: 1TB Seagate Barracuda 64MB Sata III 7200RPM (2x - RAID 0)
*HD²: SAMSUNG M3 Externo USB 5400RPM 1TB
*Placa de vídeo: Nvidia GTX660 2GB DDR5 192bit EVGA
*RAM: 8GB DDR3 1600MHZ Kingston HYPER X BEAST (2x4GB)
*Fonte: Corsair 600W Reais CX600M Modular - CP-9020060-WW (80 Plus Bronze)
*Gabinete: Gabinete Raidmax Super Hurricane Branco - 248WB
*Monitor: LG 23MP55HQ Full HD HDMI 23'
Conteúdo patrocinado
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum