2014-08-28 6 views
1

Есть ли способ изменить десятичный разделитель периода для запятой ?.Fortran десятичный и тысячный разделитель

Кроме того, как я могу сделать выходные номера с тысячами разделителей ?. Это может быть запятая, период, пространство ...

+1

я на самом деле задавал подобный вопрос: http://stackoverflow.com/a/21117594/ 2432130 –

+0

@AlexanderVogt @Alex Разница заключается в тысячах разделителей, что довольно сложно. Местные локаторы POSIX знают это, но C 'printf' и' sprintf' игнорируют его. –

+0

Хорошо, @Alex, так что: 'write (*, '(dc, f12.3)') 12.3' устанавливает десятичный разделитель, который я хочу. Но все еще остается проблема тысяч разделителей. –

ответ

3

использовать аргумент DECIMAL = «запятую» при открытии файла

open(100,file=logfile,status='unknown',DECIMAL='COMMA') 

Это изменит десятичную запятую в

+2

Да, но, а как же, если я хочу напечатать цифры на экране ?. А как насчет тысячи разделителей? –

4

Вы можете напишите функцию C++, которая преобразует число в строку в вашей текущей локали для вас.

#include <string> 
#include <iomanip> 
#include <sstream> 

class SpaceSeparator: public std::numpunct<char> 
{ 
public: 
    SpaceSeparator(std::size_t refs): std::numpunct<char>(refs) {} 
protected: 
    char do_thousands_sep() const { return ' '; } 
    char do_decimal_point() const { return ','; } 
    std::string do_grouping() const { return "\03"; } 
}; 

extern "C" { 

void convert(char* str, double f, int len) { 
    std::string s; 
    std::stringstream out; 
    SpaceSeparator facet(1); //1 - don't delete when done 
    std::locale prev = out.imbue(std::locale(std::locale(), &facet)); 
    out << std::setprecision(15) << f; 

    s = out.str(); 
    std::copy(s.begin(), s.end(), str); 
    int i; 
    for (i=s.size();i<len;i++){ 
    str[i] = ' '; 
    } 
} 

} 

звонок из Fortran:

use iso_c_binding 

    interface 
    subroutine convert(str, f, l) bind(C,name="convert") 
     import 
     character(c_char) :: str(*) 
     real(c_double), value :: f 
     integer(c_int), value :: l 
    end subroutine 
    end interface 

    character(len=100,kind=c_char) :: ch 

    call convert(ch, 123456.123_c_double, len(ch, kind=c_int)) 
    print *,ch 
end 

На моей машине печатает 123 456,123:

> gfortran locale.cc locale.f90 -lstdc++ 
> ./a.out 
123 456,123         

Отказ от ответственности: Я не программист C++, и он решение может быть медленным. Возможно, более грубый подход в Фортране.

Я использовал этот ответ в качестве основы: https://stackoverflow.com/a/2648663/721644

+0

Спасибо. Но я думаю, что я попробую использовать более сложный подход Fortran_, программируя собственную функцию в Fortran для управления десятичными и тысячными разделителями. –

+0

@AntonioSerrano Вы можете начать с ответа Джорджа. –

2

быстрый и грязный Фортран подход, основанный на:

implicit none 

    write(*,*) commadelim(123456.789) 
    write(*,*) commadelim(23456.789) 
    write(*,*) commadelim(3456.789) 
    write(*,*) commadelim(-123456.789) 
    write(*,*) commadelim(-23456.789) 
    write(*,*) commadelim(-3456.789) 

    contains 

    function commadelim(v) 
     implicit none 

     real v 
     integer dp,p,z0,i 
     character(len=50) :: commadelim 

     write(commadelim,'(f0.12)') abs(v)  
     dp = index(commadelim,'.') 
     commadelim(dp:dp) = ',' 
     z0 = 2 - mod(dp+1,3) 

     do i = 1, (dp+z0-1)/3-1 
     p = 4*i-z0 
     commadelim = commadelim(:p)//'.'//commadelim(p+1:) 
     enddo 

     if (v<0) commadelim = '-'//commadelim 
    end function 
    end 
+1

+1, но я добавил некоторое форматирование в ваш код, если вам не нравится, что часть его просто вернула его. –

+0

Я действительно не понял этот код, но теперь понимаю, что он касается как тысяч разделителей, так и десятичного разделителя. –

+0

Что более эффективно, этот код или код на C++ ?. –