Этот вопрос/проблема может быть как-то связан с Эта тема.
Если вы наберете:
print log10(1e7) вы получите 7.0.
print int(log10(1e7)) вы получите 7.
Однако, если вы наберете
print log10(1e6) вы получите 6.0.
print int(log10(1e6)) вы получите 5.
Вероятно, это ошибки округления, связанные с log10, и их нельзя (?) избежать.
Потому что, если вы наберете
print sprintf("%.20e",log10(1e6)) дает 5.99999999999999911182e+00
print sprintf("%.20e",log10(1e7)) дает 7.00000000000000000000e+00
Вы можете расширить и обобщить это как сюжет: Код:
### power problem in gnuplot
reset session
set colorsequence classic
set key left
set samples 41
set xrange[-20:20]
plot int(log10(10**x)) w lp pt 7,\
x w lp pt 7
### end of code
Результат:
Вы увидите, что на неравномерных расстояниях есть различия между ожидаемым и полученным результатом.
Итак, мне все еще не хватает функции, которая всегда дает мне правильный порядок величины. Может быть, сначала округлить все числа до 15 знаков после запятой? Любые другие идеи?
Я согласен. Кстати, что делает sprintf("%.0e",5.99)? Вроде округляет, а не усекает. Буду ли я всегда получать ожидаемое целое число с помощью этой функции?
"%.0e" подавляет десятичную точку. См. документацию для семейства libc printf man 3 printf





предполагая, что вы не имеете дело с более чем 12-15 цифрами (или, как говорит @Ethan, более 15-16 цифр в 64-битной системе в любом случае ерунда), следующая функция должна давать правильный порядок величины как целое число. Я только что протестировал несколько примеров и сравнил их с другими «прямыми» методами. Пожалуйста, докажите, что функция правильная или неправильная.
### get the correct power of a number with gnuplot
CorrectPower(n) = floor(log10(n*(1+1e-15)))
IncorrectPower1(n) = floor(log10(n))
IncorrectPower2(n) = floor(gprintf("%T",n))
Numbers = "1e-6 1e-4 0.001 0.01 1e-2 1000 1000000 -1e-6 -1e-9 0.99 95 990"
print " Number cP icP1 icP2"
do for [i=1:words(Numbers)] {
n = word(Numbers,i)
print \
sprintf("%7s:%5d%5d%5d", n, CorrectPower(n), IncorrectPower1(n), IncorrectPower2(n))
}
### end of code
Результат:
Number cP icP1 icP2
1e-6: -6 -5 -6
1e-4: -4 -3 -4
0.001: -3 -2 -3
0.01: -2 -1 -2
1e-2: -2 -1 -2
1000: 3 2 3
1000000: 6 5 6
-1e-6: -6 -5 -6
-1e-9: -9 -8 -9
0.99: -1 0 0
95: 1 1 2
990: 2 2 3
Добавление: Для чего это стоит, еще одна функция для получения правильной мощности в виде целого числа:
CorrectPower2(n) = int(sprintf("%.15e",n)[19:])
Печать двойника в формате «%.20e» просто требует мусора. 64-битное число с плавающей запятой IEEE кодирует только 53 бита (15-16 знаков после запятой) точности. Ограничение запрошенной точности до 15 знаков после запятой не является «округлением», это просто подтверждение того, какая информация действительно присутствует.